Skip to content

Commit 6c09347

Browse files
committed
simpler
1 parent 4ad3137 commit 6c09347

1 file changed

Lines changed: 17 additions & 41 deletions

File tree

progenitor-client/src/progenitor_client.rs

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -95,36 +95,27 @@ impl std::fmt::Display for FilenameError {
9595
impl std::error::Error for FilenameError {}
9696

9797
/// A validated MIME content-type for form parts.
98-
///
99-
/// Content types are validated to have a valid `type/subtype` format.
10098
#[derive(Debug, Clone, PartialEq, Eq)]
10199
pub struct ContentType(String);
102100

103101
impl ContentType {
104102
/// Create a new content-type, validating the format.
105-
///
106-
/// # Errors
107-
/// Returns an error if the content-type doesn't follow the `type/subtype` format.
108103
pub fn new(content_type: impl Into<String>) -> Result<Self, ContentTypeError> {
109104
let content_type = content_type.into();
110-
// Basic validation: must contain exactly one '/' and non-empty parts
111-
let parts: Vec<&str> = content_type.split('/').collect();
112-
if parts.len() != 2 {
105+
let Some((type_part, rest)) = content_type.split_once('/') else {
113106
return Err(ContentTypeError::InvalidFormat);
114-
}
115-
// Get type and subtype (subtype may have parameters like charset)
116-
let type_part = parts[0].trim();
117-
let subtype_part = parts[1].split(';').next().unwrap_or("").trim();
118-
if type_part.is_empty() || subtype_part.is_empty() {
107+
};
108+
let subtype_part = rest.split_once(';').map_or(rest, |(s, _)| s);
109+
if type_part.trim().is_empty()
110+
|| subtype_part.trim().is_empty()
111+
|| subtype_part.contains('/')
112+
{
119113
return Err(ContentTypeError::InvalidFormat);
120114
}
121115
Ok(Self(content_type))
122116
}
123117

124118
/// Create a content-type without validation.
125-
///
126-
/// # Safety
127-
/// The caller must ensure the content-type is valid.
128119
pub fn new_unchecked(content_type: impl Into<String>) -> Self {
129120
Self(content_type.into())
130121
}
@@ -139,34 +130,19 @@ impl ContentType {
139130
self.0
140131
}
141132

142-
/// Common content type: `application/json`
143-
pub fn json() -> Self {
144-
Self("application/json".to_string())
145-
}
146-
147-
/// Common content type: `application/octet-stream`
148-
pub fn octet_stream() -> Self {
149-
Self("application/octet-stream".to_string())
150-
}
151-
152-
/// Common content type: `text/plain`
153-
pub fn text_plain() -> Self {
154-
Self("text/plain".to_string())
155-
}
156-
157-
/// Common content type: `application/pdf`
158-
pub fn pdf() -> Self {
159-
Self("application/pdf".to_string())
133+
/// Create `application/{subtype}` content type.
134+
pub fn application(subtype: impl AsRef<str>) -> Self {
135+
Self(format!("application/{}", subtype.as_ref()))
160136
}
161137

162-
/// Common content type: `image/png`
163-
pub fn png() -> Self {
164-
Self("image/png".to_string())
138+
/// Create `text/{subtype}` content type.
139+
pub fn text(subtype: impl AsRef<str>) -> Self {
140+
Self(format!("text/{}", subtype.as_ref()))
165141
}
166142

167-
/// Common content type: `image/jpeg`
168-
pub fn jpeg() -> Self {
169-
Self("image/jpeg".to_string())
143+
/// Create `image/{subtype}` content type.
144+
pub fn image(subtype: impl AsRef<str>) -> Self {
145+
Self(format!("image/{}", subtype.as_ref()))
170146
}
171147
}
172148

@@ -286,7 +262,7 @@ impl TextFormPart {
286262
pub fn json<T: serde::Serialize>(value: &T) -> Result<Self, serde_json::Error> {
287263
Ok(Self {
288264
value: serde_json::to_string(value)?,
289-
content_type: Some(ContentType::json()),
265+
content_type: Some(ContentType::application("json")),
290266
})
291267
}
292268

0 commit comments

Comments
 (0)