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;