use super::{
content_type,
header_parameter::{
leading_token,
parse_parameters,
},
};
#[must_use]
pub(in crate::http) struct MultipartPartMetadata<'a> {
name: Option<String>,
filename: Option<String>,
content_type: Option<&'a str>,
}
impl<'a> MultipartPartMetadata<'a> {
#[must_use]
#[inline]
pub(super) fn parse(
disposition: Option<&str>,
content_type: Option<&'a str>,
require_form_data: bool,
) -> Option<Self> {
if content_type.is_some_and(|value| !content_type::is_valid(value)) {
return None;
}
let [name, filename, extended] = match disposition {
Some(disposition) => {
let disposition_kind = leading_token(disposition)?;
if require_form_data
&& !disposition_kind.eq_ignore_ascii_case("form-data")
{
return None;
}
parse_parameters(
disposition,
["name", "filename", "filename*"],
)?
}
None if require_form_data => return None,
None => [None, None, None],
};
Some(Self {
name: name.filter(|value| !value.trim().is_empty()),
filename: filename.or(extended),
content_type,
})
}
#[must_use]
#[inline(always)]
pub(super) fn name(&self) -> Option<&str> {
self.name.as_deref()
}
#[must_use]
#[inline(always)]
pub(super) fn filename(&self) -> Option<&str> {
self.filename.as_deref()
}
#[must_use]
#[inline(always)]
pub(super) const fn content_type(&self) -> Option<&'a str> {
self.content_type
}
}