Skip to main content

parse_net/sfv/
mod.rs

1//! Structured Field Values (RFC 9651): Items, Lists, and Dictionaries with
2//! every bare item type, parsed into borrowed views.
3//!
4//! The parser follows RFC 9651 section 4.2 exactly, as a loop with explicit
5//! state; inner lists cannot nest, so there is no recursion. A field is
6//! accepted or refused as a whole, as section 4.2 requires. Every limit of
7//! section 3 is enforced through [`Limits`], whose defaults meet each
8//! minimum.
9//!
10//! # Examples
11//!
12//! ```
13//! use parse_net::sfv::{self, BareItem, Member};
14//!
15//! let site = sfv::parse_item(b"same-origin")?;
16//! assert_eq!(site.bare, BareItem::Token("same-origin"));
17//!
18//! let prio = sfv::parse_dictionary(b"u=1, i")?;
19//! assert!(matches!(prio.get("u"), Some(Member::Item(i)) if i.bare == BareItem::Integer(1)));
20//! assert!(matches!(prio.get("i"), Some(Member::Item(i)) if i.bare == BareItem::Boolean(true)));
21//!
22//! let list = sfv::parse_list(b"(\"foo\" \"bar\");lvl=5, abc;a=?0")?;
23//! assert_eq!(list.len(), 2);
24//! let Some(Member::InnerList(inner)) = list.iter().next() else { unreachable!() };
25//! assert_eq!(inner.len(), 2);
26//! # Ok::<(), parse_net::ParseError>(())
27//! ```
28
29mod parse;
30
31use parse::{Cursor, Events, Nothing};
32
33use crate::{
34    error::{ErrorKind, ParseError, Result, err},
35    limits::Limits,
36};
37
38/// Limits for walking text that was already validated: every bound at its
39/// maximum, so a view never refuses what its parse accepted.
40const RELAXED: Limits = Limits::DEFAULT
41    .max_list_members(u16::MAX)
42    .max_inner_list_members(u16::MAX)
43    .max_params(u16::MAX)
44    .max_dictionary_members(u16::MAX)
45    .max_key_len(u16::MAX)
46    .max_string_len(u16::MAX)
47    .max_token_len(u16::MAX)
48    .max_byte_seq_len(u32::MAX);
49
50/// A bare item (RFC 9651 section 3.3).
51#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
52pub enum BareItem<'a> {
53    /// An Integer, at most 15 digits.
54    Integer(i64),
55    /// A Decimal, in thousandths.
56    Decimal(Decimal),
57    /// A String.
58    String(SfString<'a>),
59    /// A Token (ASCII by construction).
60    Token(&'a str),
61    /// A Byte Sequence, still base64.
62    ByteSeq(ByteSeq<'a>),
63    /// A Boolean.
64    Boolean(bool),
65    /// A Date: seconds since the Unix epoch, within years 1 to 9999.
66    Date(i64),
67    /// A Display String, still percent-encoded.
68    DisplayString(DisplayString<'a>),
69}
70
71/// A Decimal in thousandths: at most 12 integer and 3 fractional digits.
72///
73/// # Examples
74///
75/// ```
76/// use parse_net::sfv::{self, BareItem, Decimal};
77///
78/// assert_eq!(sfv::parse_item(b"-1.5")?.bare, BareItem::Decimal(Decimal::from_thousandths(-1500)?));
79/// assert!(Decimal::from_thousandths(1_000_000_000_000_000).is_err());
80/// # Ok::<(), parse_net::ParseError>(())
81/// ```
82#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
83pub struct Decimal(pub(crate) i64);
84
85impl Decimal {
86    /// The decimal `t / 1000`.
87    ///
88    /// # Errors
89    ///
90    /// [`ErrorKind::OutOfRange`] beyond 12 integer digits.
91    pub const fn from_thousandths(t: i64) -> Result<Self> {
92        if t > parse::INTEGER_MAX || t < -parse::INTEGER_MAX {
93            return err(ErrorKind::OutOfRange, 0);
94        }
95        Ok(Self(t))
96    }
97
98    /// The value in thousandths.
99    #[must_use]
100    pub const fn thousandths(self) -> i64 {
101        self.0
102    }
103}
104
105/// A String: the content between the quotes, only `\"` and `\\` escapes.
106#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
107pub struct SfString<'a> {
108    raw: &'a str,
109    escapes: bool,
110}
111
112impl<'a> SfString<'a> {
113    /// The content as sent, escapes included (ASCII by construction).
114    #[must_use]
115    pub const fn raw(&self) -> &'a str {
116        self.raw
117    }
118
119    /// The value with no copy, when it has no escape.
120    #[must_use]
121    pub const fn as_plain(&self) -> Option<&'a str> {
122        if self.escapes { None } else { Some(self.raw) }
123    }
124
125    fn bytes(&self) -> crate::text::Unescape<'a> {
126        crate::text::Quoted::from_raw(self.raw.as_bytes(), self.escapes).bytes()
127    }
128
129    /// The length of the unescaped value.
130    #[must_use]
131    pub fn unescaped_len(&self) -> usize {
132        if self.escapes {
133            self.bytes().count()
134        } else {
135            self.raw.len()
136        }
137    }
138
139    /// Writes the unescaped value into `out` and returns it.
140    ///
141    /// # Errors
142    ///
143    /// [`ErrorKind::BufferTooSmall`]; nothing is written.
144    ///
145    /// # Examples
146    ///
147    /// ```
148    /// use parse_net::sfv::{self, BareItem};
149    ///
150    /// let BareItem::String(s) = sfv::parse_item(b"\"a \\\"b\\\"\"")?.bare else { unreachable!() };
151    /// let mut buf = [0u8; 8];
152    /// assert_eq!(s.unescape_into(&mut buf)?, "a \"b\"");
153    /// assert!(s.eq_str("a \"b\""));
154    /// # Ok::<(), parse_net::ParseError>(())
155    /// ```
156    pub fn unescape_into<'b>(&self, out: &'b mut [u8]) -> Result<&'b str> {
157        let len = self.unescaped_len();
158        let Some(dst) = out.get_mut(..len) else {
159            return err(ErrorKind::BufferTooSmall, 0);
160        };
161        for (d, b) in dst.iter_mut().zip(self.bytes()) {
162            *d = b;
163        }
164        // ASCII in, ASCII out.
165        core::str::from_utf8(dst).map_err(|_| ParseError::new(ErrorKind::InvalidUtf8, 0))
166    }
167
168    /// Whether the unescaped value equals `other`, with no buffer.
169    #[must_use]
170    pub fn eq_str(&self, other: &str) -> bool {
171        self.bytes().eq(other.bytes())
172    }
173}
174
175/// A Byte Sequence: the base64 text between the colons.
176#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
177pub struct ByteSeq<'a> {
178    raw: &'a [u8],
179}
180
181impl<'a> ByteSeq<'a> {
182    /// The base64 text, padding included if it was sent.
183    #[must_use]
184    pub const fn raw(&self) -> &'a [u8] {
185        self.raw
186    }
187
188    /// The exact length of the decoded bytes.
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// use parse_net::sfv::{self, BareItem};
194    ///
195    /// let BareItem::ByteSeq(b) = sfv::parse_item(b":cHJldGVuZCB0aGlzIGlzIGJpbmFyeSBjb250ZW50Lg==:")?.bare else { unreachable!() };
196    /// assert_eq!(b.decoded_len(), 31);
197    /// # Ok::<(), parse_net::ParseError>(())
198    /// ```
199    #[must_use]
200    pub fn decoded_len(&self) -> usize {
201        let body = self.raw.iter().take_while(|&&b| b != b'=').count();
202        body / 4 * 3 + (body % 4).saturating_sub(1)
203    }
204}
205
206/// A Display String: the percent-encoded text between the quotes, validated
207/// as UTF-8 during the parse.
208#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
209pub struct DisplayString<'a> {
210    raw: &'a [u8],
211}
212
213impl<'a> DisplayString<'a> {
214    /// The text as sent, `%xx` triples included.
215    #[must_use]
216    pub const fn raw(&self) -> &'a [u8] {
217        self.raw
218    }
219
220    /// The length of the decoded UTF-8 text.
221    #[must_use]
222    pub fn decoded_len(&self) -> usize {
223        crate::pct::decoded_len(self.raw).unwrap_or(0)
224    }
225
226    /// Writes the decoded text into `out` and returns it.
227    ///
228    /// # Errors
229    ///
230    /// [`ErrorKind::BufferTooSmall`]; nothing is written.
231    ///
232    /// # Examples
233    ///
234    /// ```
235    /// use parse_net::sfv::{self, BareItem};
236    ///
237    /// let BareItem::DisplayString(d) = sfv::parse_item(b"%\"caf%c3%a9\"")?.bare else { unreachable!() };
238    /// let mut buf = [0u8; 8];
239    /// assert_eq!(d.decode_into(&mut buf)?, "caf\u{e9}");
240    /// # Ok::<(), parse_net::ParseError>(())
241    /// ```
242    pub fn decode_into<'b>(&self, out: &'b mut [u8]) -> Result<&'b str> {
243        crate::pct::decode_utf8_into(self.raw, out)
244    }
245}
246
247/// Parameters of an item or an inner list. A repeated key keeps every
248/// occurrence; [`get`](Self::get) takes the last, as RFC 9651 requires.
249#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
250pub struct SfParams<'a> {
251    text: &'a [u8],
252    count: usize,
253}
254
255impl<'a> SfParams<'a> {
256    const EMPTY: Self = Self {
257        text: &[],
258        count: 0,
259    };
260
261    /// The parameters, in order.
262    #[must_use]
263    pub fn iter(&self) -> ParamIter<'a> {
264        ParamIter {
265            c: Cursor::new(self.text),
266        }
267    }
268
269    /// The value of `key`: the last occurrence.
270    #[must_use]
271    pub fn get(&self, key: &str) -> Option<BareItem<'a>> {
272        self.iter()
273            .filter(|(k, _)| *k == key)
274            .last()
275            .map(|(_, v)| v)
276    }
277
278    /// The number of parameters, repeats included.
279    #[must_use]
280    pub const fn len(&self) -> usize {
281        self.count
282    }
283
284    /// Whether there are no parameters.
285    #[must_use]
286    pub const fn is_empty(&self) -> bool {
287        self.count == 0
288    }
289}
290
291/// The parameters of a validated [`SfParams`].
292#[derive(Clone, Debug)]
293pub struct ParamIter<'a> {
294    c: Cursor<'a>,
295}
296
297impl<'a> Iterator for ParamIter<'a> {
298    type Item = (&'a str, BareItem<'a>);
299
300    fn next(&mut self) -> Option<Self::Item> {
301        if self.c.peek() != Some(b';') {
302            return None;
303        }
304        self.c.bump();
305        self.c.skip_sp();
306        let k = parse::key(&mut self.c, &RELAXED).ok()?;
307        let v = if self.c.peek() == Some(b'=') {
308            self.c.bump();
309            parse::bare_item(&mut self.c, &RELAXED).ok()?
310        } else {
311            BareItem::Boolean(true)
312        };
313        Some((k, v))
314    }
315}
316
317/// An item: a bare item and its parameters.
318#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
319pub struct Item<'a> {
320    /// The bare item.
321    pub bare: BareItem<'a>,
322    /// Its parameters.
323    pub params: SfParams<'a>,
324}
325
326/// An inner list: items in parentheses, and its own parameters.
327#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
328pub struct InnerList<'a> {
329    text: &'a [u8],
330    count: usize,
331    params: SfParams<'a>,
332}
333
334impl<'a> InnerList<'a> {
335    /// The items, in order.
336    #[must_use]
337    pub fn iter(&self) -> InnerIter<'a> {
338        let mut c = Cursor::new(self.text);
339        c.bump(); // "("
340        InnerIter { c }
341    }
342
343    /// The number of items.
344    #[must_use]
345    pub const fn len(&self) -> usize {
346        self.count
347    }
348
349    /// Whether the inner list is empty (`()`).
350    #[must_use]
351    pub const fn is_empty(&self) -> bool {
352        self.count == 0
353    }
354
355    /// The inner list's own parameters.
356    #[must_use]
357    pub const fn params(&self) -> SfParams<'a> {
358        self.params
359    }
360}
361
362/// The items of a validated [`InnerList`].
363#[derive(Clone, Debug)]
364pub struct InnerIter<'a> {
365    c: Cursor<'a>,
366}
367
368impl<'a> Iterator for InnerIter<'a> {
369    type Item = Item<'a>;
370
371    fn next(&mut self) -> Option<Item<'a>> {
372        self.c.skip_sp();
373        if matches!(self.c.peek(), Some(b')') | None) {
374            return None;
375        }
376        item_view(&mut self.c)
377    }
378}
379
380/// A list or dictionary member.
381#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
382pub enum Member<'a> {
383    /// An item.
384    Item(Item<'a>),
385    /// An inner list.
386    InnerList(InnerList<'a>),
387}
388
389/// Parses an item at the cursor of validated text.
390fn item_view<'a>(c: &mut Cursor<'a>) -> Option<Item<'a>> {
391    let bare = parse::bare_item(c, &RELAXED).ok()?;
392    let params = params_view(c)?;
393    Some(Item { bare, params })
394}
395
396fn params_view<'a>(c: &mut Cursor<'a>) -> Option<SfParams<'a>> {
397    let start = c.i;
398    let count = parse::params(c, &RELAXED, |_, _| Ok(())).ok()?;
399    Some(SfParams {
400        text: c.s.get(start..c.i).unwrap_or(&[]),
401        count,
402    })
403}
404
405/// Parses a member at the cursor of validated text.
406fn member_view<'a>(c: &mut Cursor<'a>) -> Option<Member<'a>> {
407    if c.peek() != Some(b'(') {
408        return item_view(c).map(Member::Item);
409    }
410    let start = c.i;
411    let mut inner = *c;
412    inner.bump(); // "("
413    let mut count = 0usize;
414    loop {
415        inner.skip_sp();
416        match inner.peek() {
417            Some(b')') => {
418                inner.bump();
419                break;
420            }
421            None => return None,
422            Some(_) => {}
423        }
424        let _ = item_view(&mut inner)?;
425        count += 1;
426    }
427    let text = c.s.get(start..inner.i).unwrap_or(&[]);
428    let params = params_view(&mut inner)?;
429    *c = inner;
430    Some(Member::InnerList(InnerList {
431        text,
432        count,
433        params,
434    }))
435}
436
437/// The value of a validated field line with its surrounding SP removed.
438fn field_text(v: &[u8]) -> Cursor<'_> {
439    let start = v.iter().take_while(|&&b| b == b' ').count();
440    let end = v.len() - v.iter().rev().take_while(|&&b| b == b' ').count();
441    Cursor::new(v.get(start..end.max(start)).unwrap_or(&[]))
442}
443
444/// Advances past the separator after a member of validated text; `false` at
445/// the end.
446fn next_member(c: &mut Cursor<'_>) -> bool {
447    c.skip_ows();
448    if c.peek() != Some(b',') {
449        return false;
450    }
451    c.bump();
452    c.skip_ows();
453    true
454}
455
456/// A validated List.
457#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
458pub struct List<'a> {
459    text: &'a [u8],
460    count: usize,
461}
462
463impl<'a> List<'a> {
464    /// The members, in order.
465    #[must_use]
466    pub fn iter(&self) -> ListIter<'a> {
467        ListIter {
468            c: Cursor::new(self.text),
469            started: false,
470        }
471    }
472
473    /// The number of members.
474    #[must_use]
475    pub const fn len(&self) -> usize {
476        self.count
477    }
478
479    /// Whether the list is empty.
480    #[must_use]
481    pub const fn is_empty(&self) -> bool {
482        self.count == 0
483    }
484}
485
486/// The members of a validated [`List`].
487#[derive(Clone, Debug)]
488pub struct ListIter<'a> {
489    c: Cursor<'a>,
490    started: bool,
491}
492
493impl<'a> Iterator for ListIter<'a> {
494    type Item = Member<'a>;
495
496    fn next(&mut self) -> Option<Member<'a>> {
497        if self.started && !next_member(&mut self.c) {
498            return None;
499        }
500        self.started = true;
501        if self.c.is_empty() {
502            return None;
503        }
504        member_view(&mut self.c)
505    }
506}
507
508/// A validated Dictionary. Every member is kept in order; a repeated key's
509/// last value wins in [`get`](Self::get) and [`index_into`](Self::index_into).
510#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
511pub struct Dictionary<'a> {
512    text: &'a [u8],
513    count: usize,
514}
515
516impl<'a> Dictionary<'a> {
517    /// The members with their keys, in order (repeats included).
518    #[must_use]
519    pub fn iter(&self) -> DictIter<'a> {
520        DictIter {
521            c: Cursor::new(self.text),
522            started: false,
523        }
524    }
525
526    /// The member for `key`: the last occurrence.
527    #[must_use]
528    pub fn get(&self, key: &str) -> Option<Member<'a>> {
529        self.iter()
530            .filter(|(k, _)| *k == key)
531            .last()
532            .map(|(_, m)| m)
533    }
534
535    /// Fills `slots` with one entry per distinct key (the last value for a
536    /// repeated key), in first-seen order, and returns the filled part: for
537    /// callers that look up many keys.
538    ///
539    /// # Errors
540    ///
541    /// [`ErrorKind::BufferTooSmall`] when there are more distinct keys than
542    /// slots.
543    ///
544    /// # Examples
545    ///
546    /// ```
547    /// use parse_net::sfv::{self, BareItem, Item, Member};
548    ///
549    /// let d = sfv::parse_dictionary(b"a=1, b=2, a=3")?;
550    /// let mut slots = [("", Member::Item(Item::new(BareItem::Boolean(false)))); 4];
551    /// let index = d.index_into(&mut slots)?;
552    /// assert_eq!(index.len(), 2);
553    /// assert!(matches!(index[0], ("a", Member::Item(i)) if i.bare == BareItem::Integer(3)));
554    /// # Ok::<(), parse_net::ParseError>(())
555    /// ```
556    pub fn index_into<'i>(
557        &self,
558        slots: &'i mut [(&'a str, Member<'a>)],
559    ) -> Result<&'i [(&'a str, Member<'a>)]> {
560        let mut n = 0usize;
561        for (k, m) in self.iter() {
562            let existing = slots
563                .get_mut(..n)
564                .and_then(|filled| filled.iter_mut().find(|(sk, _)| *sk == k));
565            match existing {
566                Some(slot) => slot.1 = m,
567                None => {
568                    let Some(slot) = slots.get_mut(n) else {
569                        return err(ErrorKind::BufferTooSmall, 0);
570                    };
571                    *slot = (k, m);
572                    n += 1;
573                }
574            }
575        }
576        Ok(slots.get(..n).unwrap_or(&[]))
577    }
578
579    /// The number of members, repeats included.
580    #[must_use]
581    pub const fn len(&self) -> usize {
582        self.count
583    }
584
585    /// Whether the dictionary is empty.
586    #[must_use]
587    pub const fn is_empty(&self) -> bool {
588        self.count == 0
589    }
590}
591
592/// The members of a validated [`Dictionary`].
593#[derive(Clone, Debug)]
594pub struct DictIter<'a> {
595    c: Cursor<'a>,
596    started: bool,
597}
598
599impl<'a> Iterator for DictIter<'a> {
600    type Item = (&'a str, Member<'a>);
601
602    fn next(&mut self) -> Option<Self::Item> {
603        if self.started && !next_member(&mut self.c) {
604            return None;
605        }
606        self.started = true;
607        if self.c.is_empty() {
608            return None;
609        }
610        let k = parse::key(&mut self.c, &RELAXED).ok()?;
611        let m = if self.c.peek() == Some(b'=') {
612            self.c.bump();
613            member_view(&mut self.c)?
614        } else {
615            Member::Item(Item {
616                bare: BareItem::Boolean(true),
617                params: params_view(&mut self.c)?,
618            })
619        };
620        Some((k, m))
621    }
622}
623
624/// Several field lines read as one List.
625#[derive(Clone, Copy, Debug)]
626pub struct ListLines<'a> {
627    lines: &'a [&'a [u8]],
628    count: usize,
629}
630
631impl<'a> ListLines<'a> {
632    /// The members of every line, in order.
633    pub fn iter(&self) -> impl Iterator<Item = Member<'a>> + use<'a> {
634        self.lines.iter().flat_map(|l| ListIter {
635            c: field_text(l),
636            started: false,
637        })
638    }
639
640    /// The number of members across every line.
641    #[must_use]
642    pub const fn len(&self) -> usize {
643        self.count
644    }
645
646    /// Whether no line has a member.
647    #[must_use]
648    pub const fn is_empty(&self) -> bool {
649        self.count == 0
650    }
651}
652
653/// Several field lines read as one Dictionary.
654#[derive(Clone, Copy, Debug)]
655pub struct DictionaryLines<'a> {
656    lines: &'a [&'a [u8]],
657    count: usize,
658}
659
660impl<'a> DictionaryLines<'a> {
661    /// The members of every line, in order.
662    pub fn iter(&self) -> impl Iterator<Item = (&'a str, Member<'a>)> + use<'a> {
663        self.lines.iter().flat_map(|l| DictIter {
664            c: field_text(l),
665            started: false,
666        })
667    }
668
669    /// The member for `key`: the last occurrence across every line.
670    #[must_use]
671    pub fn get(&self, key: &str) -> Option<Member<'a>> {
672        self.iter()
673            .filter(|(k, _)| *k == key)
674            .last()
675            .map(|(_, m)| m)
676    }
677
678    /// The number of members across every line, repeats included.
679    #[must_use]
680    pub const fn len(&self) -> usize {
681        self.count
682    }
683
684    /// Whether no line has a member.
685    #[must_use]
686    pub const fn is_empty(&self) -> bool {
687        self.count == 0
688    }
689}
690
691/// Receives a parse as events: the single-pass form, for callers that read
692/// one key or count items without building a view.
693///
694/// # Examples
695///
696/// ```
697/// use parse_net::{sfv::{BareItem, Parser, Visitor}, Limits, ParseError};
698///
699/// struct Urgency(Option<i64>, bool);
700/// impl<'a> Visitor<'a> for Urgency {
701///     fn item(&mut self, bare: BareItem<'a>) -> Result<(), ParseError> {
702///         if let (true, BareItem::Integer(u)) = (self.1, bare) { self.0 = Some(u); }
703///         Ok(())
704///     }
705///     fn param(&mut self, _: &'a str, _: BareItem<'a>) -> Result<(), ParseError> { Ok(()) }
706///     fn key(&mut self, key: &'a str) -> Result<(), ParseError> { self.1 = key == "u"; Ok(()) }
707/// }
708///
709/// let mut v = Urgency(None, false);
710/// Parser::new(Limits::DEFAULT).visit_dictionary(b"u=5, i", &mut v)?;
711/// assert_eq!(v.0, Some(5));
712/// # Ok::<(), ParseError>(())
713/// ```
714pub trait Visitor<'a> {
715    /// A bare item: a member, an inner-list item, or a dictionary value.
716    ///
717    /// # Errors
718    ///
719    /// Any error stops the parse and is returned.
720    fn item(&mut self, bare: BareItem<'a>) -> Result<()>;
721
722    /// A parameter of the most recent item or inner list.
723    ///
724    /// # Errors
725    ///
726    /// Any error stops the parse and is returned.
727    fn param(&mut self, key: &'a str, value: BareItem<'a>) -> Result<()>;
728
729    /// An inner list begins.
730    ///
731    /// # Errors
732    ///
733    /// Any error stops the parse and is returned.
734    fn inner_list_start(&mut self) -> Result<()> {
735        Ok(())
736    }
737
738    /// An inner list ends (its parameters follow).
739    ///
740    /// # Errors
741    ///
742    /// Any error stops the parse and is returned.
743    fn inner_list_end(&mut self) -> Result<()> {
744        Ok(())
745    }
746
747    /// A dictionary key; its value follows.
748    ///
749    /// # Errors
750    ///
751    /// Any error stops the parse and is returned.
752    fn key(&mut self, key: &'a str) -> Result<()> {
753        let _ = key;
754        Ok(())
755    }
756}
757
758struct VisitorEvents<'v, V>(&'v mut V);
759
760impl<'a, V: Visitor<'a>> Events<'a> for VisitorEvents<'_, V> {
761    fn item(&mut self, bare: BareItem<'a>) -> Result<()> {
762        self.0.item(bare)
763    }
764    fn param(&mut self, key: &'a str, value: BareItem<'a>) -> Result<()> {
765        self.0.param(key, value)
766    }
767    fn inner_start(&mut self) -> Result<()> {
768        self.0.inner_list_start()
769    }
770    fn inner_end(&mut self) -> Result<()> {
771        self.0.inner_list_end()
772    }
773    fn key(&mut self, key: &'a str) -> Result<()> {
774        self.0.key(key)
775    }
776}
777
778/// The configurable parser.
779#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
780pub struct Parser {
781    limits: Limits,
782}
783
784impl Default for Parser {
785    fn default() -> Self {
786        Self::new(Limits::DEFAULT)
787    }
788}
789
790impl Parser {
791    /// A parser with `limits`.
792    #[must_use]
793    pub const fn new(limits: Limits) -> Self {
794        Self { limits }
795    }
796
797    /// Parses an Item (section 4.2.3).
798    ///
799    /// # Errors
800    ///
801    /// See [`parse_item`].
802    pub fn item<'a>(&self, v: &'a [u8]) -> Result<Item<'a>> {
803        let l = self.limits;
804        let ((bare, params), _, _) = parse::field(v, |c| {
805            let bare = parse::bare_item(c, &l)?;
806            let start = c.i;
807            let count = parse::params(c, &l, |_, _| Ok(()))?;
808            Ok((
809                bare,
810                SfParams {
811                    text: c.s.get(start..c.i).unwrap_or(&[]),
812                    count,
813                },
814            ))
815        })?;
816        Ok(Item { bare, params })
817    }
818
819    /// Parses a List (section 4.2.1).
820    ///
821    /// # Errors
822    ///
823    /// See [`parse_list`].
824    pub fn list<'a>(&self, v: &'a [u8]) -> Result<List<'a>> {
825        let l = self.limits;
826        let (count, start, end) = parse::field(v, |c| parse::list(c, &l, &mut Nothing))?;
827        Ok(List {
828            text: v.get(start..end).unwrap_or(&[]),
829            count,
830        })
831    }
832
833    /// Parses a Dictionary (section 4.2.2).
834    ///
835    /// # Errors
836    ///
837    /// See [`parse_dictionary`].
838    pub fn dictionary<'a>(&self, v: &'a [u8]) -> Result<Dictionary<'a>> {
839        let l = self.limits;
840        let (count, start, end) = parse::field(v, |c| parse::dictionary(c, &l, &mut Nothing))?;
841        Ok(Dictionary {
842            text: v.get(start..end).unwrap_or(&[]),
843            count,
844        })
845    }
846
847    /// Parses several field lines as one List: each line must parse on its
848    /// own, an empty line fails the field, and the member limit counts
849    /// across lines.
850    ///
851    /// # Errors
852    ///
853    /// As [`list`](Self::list), with [`ParseError::line`] set; an empty line
854    /// is [`ErrorKind::Empty`].
855    pub fn list_lines<'a>(&self, lines: &'a [&'a [u8]]) -> Result<ListLines<'a>> {
856        let mut count = 0usize;
857        for (n, line) in lines.iter().enumerate() {
858            if line.iter().all(|&b| b == b' ') {
859                return Err(ParseError::new(ErrorKind::Empty, 0).on_line(n));
860            }
861            count += self.list(line).map_err(|e| e.on_line(n))?.len();
862            if count > usize::from(self.limits.list_members) {
863                return Err(ParseError::new(ErrorKind::TooManyMembers, 0).on_line(n));
864            }
865        }
866        Ok(ListLines { lines, count })
867    }
868
869    /// Parses several field lines as one Dictionary (the last value of a
870    /// repeated key wins across lines).
871    ///
872    /// # Errors
873    ///
874    /// As [`list_lines`](Self::list_lines).
875    pub fn dictionary_lines<'a>(&self, lines: &'a [&'a [u8]]) -> Result<DictionaryLines<'a>> {
876        let mut count = 0usize;
877        for (n, line) in lines.iter().enumerate() {
878            if line.iter().all(|&b| b == b' ') {
879                return Err(ParseError::new(ErrorKind::Empty, 0).on_line(n));
880            }
881            count += self.dictionary(line).map_err(|e| e.on_line(n))?.len();
882            if count > usize::from(self.limits.dictionary_members) {
883                return Err(ParseError::new(ErrorKind::TooManyMembers, 0).on_line(n));
884            }
885        }
886        Ok(DictionaryLines { lines, count })
887    }
888
889    /// Parses an Item, reporting it to `visitor`.
890    ///
891    /// # Errors
892    ///
893    /// As [`item`](Self::item), or the visitor's error.
894    pub fn visit_item<'a, V: Visitor<'a>>(&self, v: &'a [u8], visitor: &mut V) -> Result<()> {
895        let l = self.limits;
896        parse::field(v, |c| {
897            let mut ev = VisitorEvents(visitor);
898            let bare = parse::bare_item(c, &l)?;
899            ev.item(bare)?;
900            parse::params(c, &l, |k, x| ev.param(k, x)).map(|_| ())
901        })
902        .map(|_| ())
903    }
904
905    /// Parses a List, reporting it to `visitor`.
906    ///
907    /// # Errors
908    ///
909    /// As [`list`](Self::list), or the visitor's error.
910    pub fn visit_list<'a, V: Visitor<'a>>(&self, v: &'a [u8], visitor: &mut V) -> Result<()> {
911        let l = self.limits;
912        parse::field(v, |c| parse::list(c, &l, &mut VisitorEvents(visitor))).map(|_| ())
913    }
914
915    /// Parses a Dictionary, reporting it to `visitor`.
916    ///
917    /// # Errors
918    ///
919    /// As [`dictionary`](Self::dictionary), or the visitor's error.
920    pub fn visit_dictionary<'a, V: Visitor<'a>>(&self, v: &'a [u8], visitor: &mut V) -> Result<()> {
921        let l = self.limits;
922        parse::field(v, |c| parse::dictionary(c, &l, &mut VisitorEvents(visitor))).map(|_| ())
923    }
924}
925
926/// Parses an Item with the default [`Limits`] (RFC 9651 section 4.2.3).
927///
928/// # Errors
929///
930/// [`ErrorKind::TrailingData`]; for the bare item:
931/// [`ErrorKind::InvalidNumber`] (`-` alone, `1.`, a Decimal after `@`),
932/// [`ErrorKind::NumberOverflow`] (16 digits, 13 integer digits in a Decimal,
933/// 4 fractional digits), [`ErrorKind::InvalidByte`],
934/// [`ErrorKind::InvalidQuotedPair`], [`ErrorKind::UnterminatedQuote`],
935/// [`ErrorKind::InvalidBase64`], [`ErrorKind::InvalidPercentEncoding`]
936/// (uppercase hex in a Display String), [`ErrorKind::InvalidUtf8`],
937/// [`ErrorKind::OutOfRange`] (a Date outside years 1 to 9999),
938/// [`ErrorKind::TooLong`]; for parameters: [`ErrorKind::InvalidKey`],
939/// [`ErrorKind::TooManyMembers`].
940///
941/// # Examples
942///
943/// ```
944/// use parse_net::sfv::{self, BareItem};
945///
946/// assert_eq!(sfv::parse_item(b"?1")?.bare, BareItem::Boolean(true));
947/// assert_eq!(sfv::parse_item(b"@1659578233")?.bare, BareItem::Date(1_659_578_233));
948/// assert!(sfv::parse_item(b"%\"%C3%A9\"").is_err());
949/// # Ok::<(), parse_net::ParseError>(())
950/// ```
951pub fn parse_item(value: &[u8]) -> Result<Item<'_>> {
952    Parser::default().item(value)
953}
954
955/// Parses a List with the default [`Limits`] (RFC 9651 section 4.2.1).
956///
957/// # Errors
958///
959/// As [`parse_item`], and [`ErrorKind::TrailingSeparator`] (`a, b,`),
960/// [`ErrorKind::ExpectedSeparator`], [`ErrorKind::TooManyMembers`].
961///
962/// # Examples
963///
964/// ```
965/// assert_eq!(parse_net::sfv::parse_list(b"a, b,").unwrap_err().kind(), parse_net::ErrorKind::TrailingSeparator);
966/// ```
967pub fn parse_list(value: &[u8]) -> Result<List<'_>> {
968    Parser::default().list(value)
969}
970
971/// Parses a Dictionary with the default [`Limits`] (RFC 9651 section 4.2.2).
972///
973/// # Errors
974///
975/// As [`parse_list`], and [`ErrorKind::InvalidKey`].
976///
977/// # Examples
978///
979/// ```
980/// use parse_net::sfv::{self, BareItem, Member};
981///
982/// let d = sfv::parse_dictionary(b"a=1, a=2")?;
983/// assert!(matches!(d.get("a"), Some(Member::Item(i)) if i.bare == BareItem::Integer(2)));
984/// # Ok::<(), parse_net::ParseError>(())
985/// ```
986pub fn parse_dictionary(value: &[u8]) -> Result<Dictionary<'_>> {
987    Parser::default().dictionary(value)
988}
989
990/// Parses several field lines as one List with the default [`Limits`].
991///
992/// # Errors
993///
994/// As [`Parser::list_lines`].
995///
996/// # Examples
997///
998/// ```
999/// let lines: [&[u8]; 2] = [b"a, b", b"c"];
1000/// assert_eq!(parse_net::sfv::parse_list_lines(&lines)?.len(), 3);
1001/// # Ok::<(), parse_net::ParseError>(())
1002/// ```
1003pub fn parse_list_lines<'a>(lines: &'a [&'a [u8]]) -> Result<ListLines<'a>> {
1004    Parser::default().list_lines(lines)
1005}
1006
1007/// Parses several field lines as one Dictionary with the default [`Limits`].
1008///
1009/// # Errors
1010///
1011/// As [`Parser::dictionary_lines`].
1012pub fn parse_dictionary_lines<'a>(lines: &'a [&'a [u8]]) -> Result<DictionaryLines<'a>> {
1013    Parser::default().dictionary_lines(lines)
1014}
1015
1016impl<'a> Item<'a> {
1017    /// An item with no parameters (for filling the slots of
1018    /// [`Dictionary::index_into`]).
1019    #[must_use]
1020    pub const fn new(bare: BareItem<'a>) -> Self {
1021        Self {
1022            bare,
1023            params: SfParams::EMPTY,
1024        }
1025    }
1026}
1027
1028#[cfg(test)]
1029mod tests;