Skip to main content

sfv/
parsed.rs

1use std::convert::Infallible;
2
3use indexmap::IndexMap;
4
5use crate::{
6    private::Sealed,
7    visitor::{
8        DictionaryVisitor, EntryVisitor, InnerListVisitor, ItemVisitor, ListVisitor,
9        ParameterVisitor,
10    },
11    BareItem, BareItemFromInput, Error, Key, KeyRef, Parser,
12};
13
14/// An [item]-type structured field value.
15///
16/// Can be used as a member of `List` or `Dictionary`.
17///
18/// [item]: <https://httpwg.org/specs/rfc9651.html#item>
19// sf-item   = bare-item parameters
20// bare-item = sf-integer / sf-decimal / sf-string / sf-token
21//             / sf-binary / sf-boolean
22#[derive(Debug, PartialEq, Clone)]
23#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
24pub struct Item {
25    /// The item's value.
26    pub bare_item: BareItem,
27    /// The item's parameters, which can be empty.
28    pub params: Parameters,
29}
30
31impl Item {
32    /// Returns a new `Item` with empty `Parameters`.
33    #[must_use]
34    pub fn new(bare_item: impl Into<BareItem>) -> Self {
35        Self {
36            bare_item: bare_item.into(),
37            params: Parameters::new(),
38        }
39    }
40
41    /// Returns a new `Item` with the given `Parameters`.
42    #[must_use]
43    pub fn with_params(bare_item: impl Into<BareItem>, params: Parameters) -> Self {
44        Self {
45            bare_item: bare_item.into(),
46            params,
47        }
48    }
49}
50
51/// A [dictionary]-type structured field value.
52///
53/// [dictionary]: <https://httpwg.org/specs/rfc9651.html#dictionary>
54// sf-dictionary  = dict-member *( OWS "," OWS dict-member )
55// dict-member    = member-name [ "=" member-value ]
56// member-name    = key
57// member-value   = sf-item / inner-list
58pub type Dictionary = IndexMap<Key, ListEntry>;
59
60/// A [list]-type structured field value.
61///
62/// [list]: <https://httpwg.org/specs/rfc9651.html#list>
63// sf-list       = list-member *( OWS "," OWS list-member )
64// list-member   = sf-item / inner-list
65pub type List = Vec<ListEntry>;
66
67/// [Parameters] of an [`Item`] or [`InnerList`].
68///
69/// [parameters]: <https://httpwg.org/specs/rfc9651.html#param>
70// parameters    = *( ";" *SP parameter )
71// parameter     = param-name [ "=" param-value ]
72// param-name    = key
73// key           = ( lcalpha / "*" )
74//                 *( lcalpha / DIGIT / "_" / "-" / "." / "*" )
75// lcalpha       = %x61-7A ; a-z
76// param-value   = bare-item
77pub type Parameters = IndexMap<Key, BareItem>;
78
79/// A member of a [`List`] or [`Dictionary`].
80#[derive(Debug, PartialEq, Clone)]
81#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
82pub enum ListEntry {
83    /// An item.
84    Item(Item),
85    /// An inner list.
86    InnerList(InnerList),
87}
88
89impl From<Item> for ListEntry {
90    fn from(item: Item) -> Self {
91        ListEntry::Item(item)
92    }
93}
94
95impl From<InnerList> for ListEntry {
96    fn from(inner_list: InnerList) -> Self {
97        ListEntry::InnerList(inner_list)
98    }
99}
100
101/// An [array] of [`Item`]s with associated [`Parameters`].
102///
103/// [array]: <https://httpwg.org/specs/rfc9651.html#inner-list>
104// inner-list    = "(" *SP [ sf-item *( 1*SP sf-item ) *SP ] ")"
105//                 parameters
106#[derive(Debug, Default, PartialEq, Clone)]
107#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
108pub struct InnerList {
109    /// The inner list's items, which can be empty.
110    pub items: Vec<Item>,
111    /// The inner list's parameters, which can be empty.
112    pub params: Parameters,
113}
114
115impl InnerList {
116    /// Returns a new `InnerList` with empty `Parameters`.
117    #[must_use]
118    pub fn new(items: Vec<Item>) -> Self {
119        Self {
120            items,
121            params: Parameters::new(),
122        }
123    }
124
125    /// Returns a new `InnerList` with the given `Parameters`.
126    #[must_use]
127    pub fn with_params(items: Vec<Item>, params: Parameters) -> Self {
128        Self { items, params }
129    }
130}
131
132impl<'de> ParameterVisitor<'de> for &mut Parameters {
133    type Error = Infallible;
134
135    fn parameter(
136        &mut self,
137        key: &'de KeyRef,
138        value: BareItemFromInput<'de>,
139    ) -> Result<(), Self::Error> {
140        self.insert(key.to_owned(), value.into());
141        Ok(())
142    }
143}
144
145impl<'de> ItemVisitor<'de> for &mut Item {
146    type Error = Infallible;
147
148    fn bare_item(
149        self,
150        bare_item: BareItemFromInput<'de>,
151    ) -> Result<impl ParameterVisitor<'de>, Self::Error> {
152        self.bare_item = bare_item.into();
153        Ok(&mut self.params)
154    }
155}
156
157impl<'de> ItemVisitor<'de> for &mut InnerList {
158    type Error = Infallible;
159    fn bare_item(
160        self,
161        bare_item: BareItemFromInput<'de>,
162    ) -> Result<impl ParameterVisitor<'de>, Self::Error> {
163        self.items.push(Item::new(bare_item));
164        match self.items.last_mut() {
165            Some(item) => Ok(&mut item.params),
166            None => unreachable!(),
167        }
168    }
169}
170
171impl<'de> InnerListVisitor<'de> for &mut InnerList {
172    type Error = Infallible;
173
174    fn item(&mut self) -> Result<impl ItemVisitor<'de>, Self::Error> {
175        Ok(&mut **self)
176    }
177
178    fn finish(self) -> Result<impl ParameterVisitor<'de>, Self::Error> {
179        Ok(&mut self.params)
180    }
181}
182
183impl<'de> DictionaryVisitor<'de> for Dictionary {
184    type Error = Infallible;
185
186    fn entry(&mut self, key: &'de KeyRef) -> Result<impl EntryVisitor<'de>, Self::Error> {
187        Ok(self.entry(key.to_owned()))
188    }
189}
190
191type Entry<'a> = indexmap::map::Entry<'a, Key, ListEntry>;
192
193impl<'de> ItemVisitor<'de> for Entry<'_> {
194    type Error = Infallible;
195
196    fn bare_item(
197        self,
198        bare_item: BareItemFromInput<'de>,
199    ) -> Result<impl ParameterVisitor<'de>, Self::Error> {
200        match self.insert_entry(Item::new(bare_item).into()).into_mut() {
201            ListEntry::Item(item) => Ok(&mut item.params),
202            ListEntry::InnerList(_) => unreachable!(),
203        }
204    }
205}
206
207impl<'de> EntryVisitor<'de> for Entry<'_> {
208    fn inner_list(self) -> Result<impl InnerListVisitor<'de>, Self::Error> {
209        match self.insert_entry(InnerList::default().into()).into_mut() {
210            ListEntry::InnerList(inner_list) => Ok(inner_list),
211            ListEntry::Item(_) => unreachable!(),
212        }
213    }
214}
215
216impl<'de> ItemVisitor<'de> for &mut List {
217    type Error = Infallible;
218
219    fn bare_item(
220        self,
221        bare_item: BareItemFromInput<'de>,
222    ) -> Result<impl ParameterVisitor<'de>, Self::Error> {
223        self.push(Item::new(bare_item).into());
224        match self.last_mut() {
225            Some(ListEntry::Item(item)) => Ok(&mut item.params),
226            _ => unreachable!(),
227        }
228    }
229}
230
231impl<'de> EntryVisitor<'de> for &mut List {
232    fn inner_list(self) -> Result<impl InnerListVisitor<'de>, Self::Error> {
233        self.push(InnerList::default().into());
234        match self.last_mut() {
235            Some(ListEntry::InnerList(inner_list)) => Ok(inner_list),
236            _ => unreachable!(),
237        }
238    }
239}
240
241impl<'de> ListVisitor<'de> for List {
242    type Error = Infallible;
243
244    fn entry(&mut self) -> Result<impl EntryVisitor<'de>, Self::Error> {
245        Ok(self)
246    }
247}
248
249/// A structured-field type, supporting parsing and serialization.
250pub trait FieldType: Sealed {
251    /// The result of serializing the value into a string.
252    ///
253    /// [`Item`] serialization is infallible; [`List`] and [`Dictionary`]
254    /// serialization is not.
255    type SerializeResult: Into<Option<String>>;
256
257    /// Serializes a structured field value into a string.
258    ///
259    /// Note: The serialization conforms to [RFC 9651], meaning that
260    /// [`Dates`][crate::Date] and [`Display Strings`][RefBareItem::DisplayString],
261    /// which cause parsing errors under [RFC 8941], will be serialized
262    /// unconditionally. The consumer of this API is responsible for determining
263    /// whether it is valid to serialize these bare items for any specific field.
264    ///
265    /// [RFC 8941]: <https://httpwg.org/specs/rfc8941.html>
266    /// [RFC 9651]: <https://httpwg.org/specs/rfc9651.html>
267    ///
268    /// Use [`crate::ItemSerializer`], [`crate::ListSerializer`], or
269    /// [`crate::DictSerializer`] to serialize components incrementally without
270    /// having to create an [`Item`], [`List`], or [`Dictionary`].
271    #[must_use]
272    fn serialize(&self) -> Self::SerializeResult;
273
274    /// Parses a structured-field value from the given parser.
275    ///
276    /// # Errors
277    /// When the parsing process is unsuccessful.
278    fn parse(parser: Parser<'_>) -> Result<Self, Error>
279    where
280        Self: Sized;
281}
282
283impl Sealed for Item {}
284
285impl FieldType for Item {
286    type SerializeResult = String;
287
288    fn serialize(&self) -> String {
289        crate::ItemSerializer::new()
290            .bare_item(&self.bare_item)
291            .parameters(&self.params)
292            .finish()
293    }
294
295    fn parse(parser: Parser<'_>) -> Result<Self, Error> {
296        let mut item = Self::new(false);
297        parser.parse_item_with_visitor(&mut item)?;
298        Ok(item)
299    }
300}
301
302impl Sealed for List {}
303
304impl FieldType for List {
305    type SerializeResult = Option<String>;
306
307    fn serialize(&self) -> Option<String> {
308        let mut ser = crate::ListSerializer::new();
309        ser.members(self);
310        ser.finish()
311    }
312
313    fn parse(parser: Parser<'_>) -> Result<Self, Error> {
314        let mut list = Self::new();
315        parser.parse_list_with_visitor(&mut list)?;
316        Ok(list)
317    }
318}
319
320impl Sealed for Dictionary {}
321
322impl FieldType for Dictionary {
323    type SerializeResult = Option<String>;
324
325    fn serialize(&self) -> Option<String> {
326        let mut ser = crate::DictSerializer::new();
327        ser.members(self);
328        ser.finish()
329    }
330
331    fn parse(parser: Parser<'_>) -> Result<Self, Error> {
332        let mut dict = Self::new();
333        parser.parse_dictionary_with_visitor(&mut dict)?;
334        Ok(dict)
335    }
336}