Skip to main content

base_web_multipart/
parameter_rules.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use base_web_media_type::MediaType;
5
6/// The rules for a `Content-Disposition` field's extended parameters, such as `filename*`, when reading its name or filename. Forms and other MIME parts follow different RFCs, so a disposition does not choose for you.
7///
8/// ```
9/// use base_web_multipart::{ContentDisposition, ParameterRules};
10/// use base_web_media_type::MediaType;
11/// use base_message::FieldType;
12///
13/// let disposition = ContentDisposition::parse(b"attachment; filename=\"EURO rates\"; filename*=utf-8''%e2%82%ac%20rates")?;
14/// assert_eq!(disposition.filename(ParameterRules::Mime)?.as_deref(), Some("€ rates"));
15/// assert!(disposition.filename(ParameterRules::FormData).is_err());
16///
17/// let rules = ParameterRules::for_media_type(&MediaType::parse("multipart/form-data; boundary=x")?);
18/// assert_eq!(rules, ParameterRules::FormData);
19/// # Ok::<(), Box<dyn std::error::Error>>(())
20/// ```
21#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
22pub enum ParameterRules {
23    /// RFC 7578, for `multipart/form-data`: extended parameters must not be used, so a disposition with any, including a continuation such as `filename*0`, is an error. Readers disagree about which of `filename` and `filename*` applies, so refusing both keeps them from seeing different names.
24    FormData,
25    /// RFC 2231, for other MIME parts, such as an email's attachments: an extended parameter, such as `filename*`, is decoded and takes the place of the plain one. Its character set must be UTF-8 or US-ASCII, and its percent-encoding valid; the language is ignored. Continuations, such as `filename*0`, are not supported yet and are an error.
26    Mime,
27}
28
29impl ParameterRules {
30    /// The rules for a body of this media type: `FormData` for `multipart/form-data`, and `Mime` for any other.
31    pub fn for_media_type(media_type: &MediaType) -> Self {
32        if media_type
33            .essence()
34            .eq_ignore_ascii_case("multipart/form-data")
35        {
36            Self::FormData
37        } else {
38            Self::Mime
39        }
40    }
41}