Skip to main content

ocpi_tariffs/
json.rs

1//! Types and functions for parsing JSON in a flexible and pedantic manner.
2#[cfg(test)]
3pub(crate) mod test;
4
5#[cfg(test)]
6mod test_path;
7
8#[cfg(test)]
9mod test_parse_with_schema;
10
11#[cfg(test)]
12mod test_source_json;
13
14#[cfg(test)]
15mod test_path_node;
16
17#[cfg(test)]
18mod test_path_node_matches_str;
19
20#[cfg(test)]
21mod test_path_matches_glob;
22
23pub mod decode;
24pub mod parser;
25pub(crate) mod schema;
26pub(crate) mod walk;
27pub mod write;
28
29use std::{
30    collections::BTreeMap,
31    fmt::{self, Write as _},
32    sync::Arc,
33};
34
35use tracing::{trace, Level};
36
37use crate::{
38    warning::{self, IntoCaveat},
39    Verdict,
40};
41use parser::ErrorKind;
42use parser::{Parser, Span};
43
44#[doc(inline)]
45pub use parser::{line_col, Error, ErrorReport, LineCol};
46pub(crate) use parser::{parse, RawStr};
47
48const PATH_SEPARATOR: char = '.';
49const PATH_ROOT: &str = "$";
50
51/// Return the `json::Element` If the given field exists(`Some`).
52/// Otherwise, add a `Warning::FieldRequired` to the set of `Warning`s and return them as an `Err`.
53#[doc(hidden)]
54#[macro_export]
55macro_rules! required_field_or_bail {
56    ($elem:expr, $fields:expr, $field_name:literal, $warnings:expr) => {
57        match $fields.get($field_name) {
58            Some(field_elem) => field_elem,
59            None => {
60                return $warnings.bail(
61                    Warning::FieldRequired {
62                        field_name: $field_name.into(),
63                    },
64                    $elem,
65                );
66            }
67        }
68    };
69}
70
71/// Return the `json::Element` If the given field exists(`Some`).
72/// Otherwise, add a `Warning::FieldRequired` to the set of `Warning`s and return them as an `Err`.
73#[doc(hidden)]
74#[macro_export]
75macro_rules! required_field {
76    ($elem:expr, $fields:expr, $field_name:literal, $warnings:expr) => {{
77        let field = $fields.get($field_name);
78
79        if field.is_none() {
80            $warnings.insert(
81                Warning::FieldRequired {
82                    field_name: $field_name.into(),
83                },
84                $elem,
85            );
86        }
87
88        field
89    }};
90}
91
92/// Return the `Field`s of the given `json::Element` if it's a JSON object.
93/// Otherwise, add a `Warning::FieldInvalidType` to the set of `Warning`s and return then as an `Err`.
94#[doc(hidden)]
95#[macro_export]
96macro_rules! expect_object_or_bail {
97    ($elem:expr, $warnings:expr) => {
98        match $elem.as_object_fields() {
99            Some(fields) => fields,
100            None => {
101                return $warnings.bail(
102                    Warning::FieldInvalidType {
103                        expected_type: json::ValueKind::Object,
104                    },
105                    $elem,
106                );
107            }
108        }
109    };
110}
111
112/// Return the `json::Element`s of the given `json::Element` if it's a JSON array.
113/// Otherwise, add a `Warning::FieldInvalidType` to the set of `Warning`s and return then as an `Err`.
114#[doc(hidden)]
115#[macro_export]
116macro_rules! expect_array_or_bail {
117    ($elem:expr, $warnings:expr) => {
118        match $elem.as_array() {
119            Some(fields) => fields,
120            None => {
121                return $warnings.bail(
122                    Warning::FieldInvalidType {
123                        expected_type: json::ValueKind::Array,
124                    },
125                    $elem,
126                );
127            }
128        }
129    };
130}
131
132/// Get a field by name and fail if it doesn't exist.
133///
134/// Convert the value of the field to the `$target` type.
135#[doc(hidden)]
136#[macro_export]
137macro_rules! parse_required_or_bail {
138    ($elem:expr, $fields:expr, $elem_name:literal, $target:ty, $warnings:expr) => {{
139        #[allow(
140            unused,
141            reason = "the macro uses the import but maybe the outside scope does too."
142        )]
143        use $crate::json::FromJson;
144        use $crate::warning::GatherWarnings as _;
145
146        let elem = $crate::required_field_or_bail!($elem, $fields, $elem_name, $warnings);
147        <$target as FromJson>::from_json(elem)?.gather_warnings_into(&mut $warnings)
148    }};
149}
150
151/// Get a field by name and return `None` if it doesn't exist.
152///
153/// Convert the value of the field to the `$target` type.
154#[doc(hidden)]
155#[macro_export]
156macro_rules! parse_required {
157    ($elem:expr, $fields:expr, $elem_name:literal, $target:ty, $warnings:expr) => {{
158        #[allow(
159            unused,
160            reason = "the macro uses the import but maybe the outside scope does too."
161        )]
162        use $crate::json::FromJson;
163        use $crate::warning::GatherWarnings as _;
164
165        let elem = $crate::required_field!($elem, $fields, $elem_name, $warnings);
166
167        if let Some(elem) = elem {
168            let value =
169                <$target as FromJson>::from_json(elem)?.gather_warnings_into(&mut $warnings);
170            Some(value)
171        } else {
172            None
173        }
174    }};
175}
176
177/// Get an optional field by name and convert the field value to the `$target` type using the
178/// blanket impl `Option<$target>` that can handle `null` JSON values.
179#[doc(hidden)]
180#[macro_export]
181macro_rules! parse_nullable_or_bail {
182    ($fields:expr, $elem_name:literal, $target:ty, $warnings:expr) => {{
183        #[allow(
184            unused,
185            reason = "the macro uses the import but maybe the outside scope does too."
186        )]
187        use $crate::json::FromJson as _;
188        use $crate::warning::GatherWarnings as _;
189
190        match $fields.get($elem_name) {
191            Some(elem) => Option::<$target>::from_json(elem)?.gather_warnings_into(&mut $warnings),
192            None => None,
193        }
194    }};
195}
196
197/// A trait for converting `Element`s to Rust types.
198pub(crate) trait FromJson<'buf>: Sized {
199    type Warning: crate::Warning;
200
201    /// Convert the given `Element` to `Self`.
202    fn from_json(elem: &Element<'buf>) -> Verdict<Self, Self::Warning>;
203}
204
205/// Implement a `null` aware variant of all types that implement `FromJson`.
206///
207/// If the value of the `json::Element` is `null` then return a `None`.
208impl<'buf, T> FromJson<'buf> for Option<T>
209where
210    T: FromJson<'buf> + IntoCaveat,
211{
212    type Warning = T::Warning;
213
214    fn from_json(elem: &Element<'buf>) -> Verdict<Self, Self::Warning> {
215        let value = elem.as_value();
216
217        if value.is_null() {
218            Ok(None.into_caveat(warning::Set::new()))
219        } else {
220            let v = T::from_json(elem)?;
221            Ok(v.map(Some))
222        }
223    }
224}
225
226/// A JSON [`Element`] composed of a `Path` and it's [`Value`].
227///
228/// The `Span` is included so that the [`Element`]'s source `&str` can be acquired from the source JSON if needed.
229#[derive(Clone, Debug, Eq, PartialEq)]
230pub struct Element<'buf> {
231    /// Used to reference the Element from `Warning`s.
232    id: ElemId,
233
234    /// The `Path` to this [`Element`].
235    path_node: PathNodeRef<'buf>,
236
237    /// The `Span` of this [`Element`].
238    ///
239    /// The `Span` defines the range of bytes that delimits this JSON [`Element`].
240    span: Span,
241
242    /// The `Value` of this [`Element`].
243    value: Value<'buf>,
244}
245
246/// A simple integer index used to ID the given [`Element`] within a JSON file.
247///
248/// The Id is unique until `usize::MAX` [`Element`]s are parsed.
249#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
250pub(crate) struct ElemId(usize);
251
252impl fmt::Display for ElemId {
253    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254        fmt::Display::fmt(&self.0, f)
255    }
256}
257
258impl<'buf> Element<'buf> {
259    /// Create a new `Element`.
260    fn new(id: ElemId, path: PathNodeRef<'buf>, span: Span, value: Value<'buf>) -> Element<'buf> {
261        Element {
262            id,
263            path_node: path,
264            span,
265            value,
266        }
267    }
268
269    /// Return the unique Id for this `Element`.
270    pub(crate) const fn id(&self) -> ElemId {
271        self.id
272    }
273
274    /// Return the `Path` to this `Element`.
275    pub fn path(&self) -> PathRef<'buf> {
276        PathRef(self.path_node())
277    }
278
279    /// Return the `PathNode` to this `Element`.
280    pub(crate) fn path_node(&self) -> PathNodeRef<'buf> {
281        Arc::clone(&self.path_node)
282    }
283
284    /// Return the `Span` of the `Element`'s `&str` is the source JSON.
285    pub fn span(&self) -> Span {
286        self.span
287    }
288
289    /// Return the source JSON `&str` of the entire Object field if the `Element` is an Object.
290    /// Otherwise, return the span of the [`Value`].
291    ///
292    /// In the case of an array like `["one", "two"]`, calling this method on the second `Element`
293    /// will return `"two"`.
294    ///
295    /// In the case of an object like `{"one": 1, "two": 2}`, calling this method on the second
296    /// `Element` will return `"\"two\": 2"`.
297    ///
298    /// # Panics
299    ///
300    /// If a source JSON is used that this `Element` didn't not originate from there is a chance
301    /// that this function will panic.
302    pub fn source_json(&self, source_json: &'buf str) -> SourceStr<'buf> {
303        if let PathNode::Object { key, .. } = *self.path_node {
304            // The span of an objects field starts from the start of the key...
305            let span = Span {
306                start: key.span().start,
307                // ... and ends at the end of the value.
308                end: self.span.end,
309            };
310            let field_str = &source_json
311                .get(span.start..span.end)
312                .expect("The disconnection between the source JSON and the `Element` will be fixed in a future PR");
313            let field = RawStr::from_str(field_str, span);
314            let (key, value) = field_str
315                .split_once(':')
316                .expect("An objects field always contains a delimiting `:`");
317
318            SourceStr::Field { field, key, value }
319        } else {
320            let span = self.span;
321            let s = source_json
322                .get(span.start..span.end)
323                .expect("The disconnection between the source JSON and the `Element` will be fixed in a future PR");
324            SourceStr::Value(RawStr::from_str(s, span))
325        }
326    }
327
328    /// Return the source JSON `&str` for the [`Value`].
329    ///
330    /// In the case of an array like `["one", "two"]`, calling this method on the second `Element`
331    /// will return `"two"`.
332    ///
333    /// In the case of an object like `{"one": 1, "two": 2}`, calling this method on the second
334    /// `Element` will return `"2"`.
335    ///
336    /// # Panics
337    ///
338    /// If a source JSON is used that this `Element` didn't not originate from there is a chance
339    /// that this function will panic.
340    pub fn source_json_value(&self, source_json: &'buf str) -> &'buf str {
341        source_json
342            .get(self.span.start..self.span.end)
343            .expect("The disconnection between the source JSON and the `Element` will be fixed in a future PR")
344    }
345
346    /// Return the `Value` of the `Element`.
347    pub(crate) fn value(&self) -> &Value<'buf> {
348        &self.value
349    }
350
351    /// Return the `&Value`.
352    pub(crate) fn as_value(&self) -> &Value<'buf> {
353        &self.value
354    }
355
356    /// Return `Some(&str)` if the `Value` is a `String`.
357    pub(crate) fn to_raw_str(&self) -> Option<RawStr<'buf>> {
358        self.value.to_raw_str()
359    }
360
361    /// Return `Some(&[Field])` if the `Value` is a `Object`.
362    pub(crate) fn as_object_fields(&self) -> Option<&[Field<'buf>]> {
363        self.value.as_object_fields()
364    }
365
366    pub(crate) fn as_array(&self) -> Option<&[Element<'buf>]> {
367        self.value.as_array()
368    }
369
370    pub fn as_number_str(&self) -> Option<&str> {
371        self.value.as_number()
372    }
373}
374
375#[derive(Debug)]
376pub enum SourceStr<'buf> {
377    /// The source `&str` of the given [`Value`].
378    Value(RawStr<'buf>),
379
380    /// The key-value pair of the given [`Element`] where the [`PathNode`] is referring to an object.
381    Field {
382        /// The entire field as a `&str`. This is the `&str` from the beginning of the key to the end of the value.
383        field: RawStr<'buf>,
384
385        /// The key excluding the separating `:`.
386        key: &'buf str,
387
388        /// The [`Value`] as `&str`.
389        value: &'buf str,
390    },
391}
392
393impl fmt::Display for SourceStr<'_> {
394    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395        match self {
396            SourceStr::Value(s) => f.write_str(s.as_raw()),
397            SourceStr::Field { field, .. } => f.write_str(field.as_raw()),
398        }
399    }
400}
401
402/// The `SourceStr` can be compared with other strings just like a `String`.
403impl PartialEq<&str> for SourceStr<'_> {
404    fn eq(&self, other: &&str) -> bool {
405        match self {
406            SourceStr::Value(s) => s.as_raw() == *other,
407            SourceStr::Field { field, .. } => field.as_raw() == *other,
408        }
409    }
410}
411
412/// The `SourceStr` can be compared with other strings just like a `String`.
413impl PartialEq<String> for SourceStr<'_> {
414    fn eq(&self, other: &String) -> bool {
415        self.eq(&&**other)
416    }
417}
418
419impl PartialOrd for Element<'_> {
420    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
421        Some(self.cmp(other))
422    }
423}
424
425impl Ord for Element<'_> {
426    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
427        self.path_node.cmp(&other.path_node)
428    }
429}
430
431impl fmt::Display for Element<'_> {
432    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433        write!(f, "{} = {}", self.path_node, self.value)
434    }
435}
436
437/// A JSON `Object`'s field that upholds the invariant that the `Element`'s `Path` is as `Object`.
438#[derive(Clone, Debug, Eq, PartialEq)]
439pub(crate) struct Field<'buf>(Element<'buf>);
440
441impl<'buf> Field<'buf> {
442    #[expect(
443        clippy::unreachable,
444        reason = "A Field is created by the parser when the type is an Object."
445    )]
446    pub(crate) fn key(&self) -> RawStr<'buf> {
447        let PathNode::Object { key, .. } = *self.0.path_node else {
448            unreachable!();
449        };
450
451        key
452    }
453
454    /// Consume the `Field` and return the inner `Element`.
455    pub(crate) fn into_element(self) -> Element<'buf> {
456        self.0
457    }
458
459    /// Consume the `Field` and return the inner `Element`.
460    pub(crate) fn element(&self) -> &Element<'buf> {
461        &self.0
462    }
463}
464
465/// A JSON `Value` that borrows it's content from the source JSON `&str`.
466#[derive(Clone, Debug, Eq, PartialEq)]
467pub(crate) enum Value<'buf> {
468    /// A `"null"` value.
469    Null,
470
471    /// A `"true"` value.
472    True,
473
474    /// A `"false"` value.
475    False,
476
477    /// The value of the `String` has the quotes trimmed.
478    String(RawStr<'buf>),
479
480    /// A JSON `Number` in string format.
481    ///
482    /// The string is not guaranteed to be a valid number. Only that it's not a `null`, `bool` or `string` value.
483    /// Convert the string into the number format you want.
484    Number(&'buf str),
485
486    /// A JSON `Array` parsed into a `Vec` of `Elements`.
487    ///
488    /// The inner `Element`'s path also encodes the index.
489    /// E.g. `$.elements.2`: This path refers to third OCPI tariff element.
490    Array(Vec<Element<'buf>>),
491
492    /// A JSON `Object` where each of the fields are parsed into a `Vec` of `Elements`.
493    ///
494    /// The inner `Element`'s path encodes the fields key.
495    /// E.g. `$.elements.2.restrictions` This path refers to the `restrictions` `Object`
496    /// of the third OCPI tariff element.
497    Object(Vec<Field<'buf>>),
498}
499
500impl<'buf> Value<'buf> {
501    pub(crate) fn kind(&self) -> ValueKind {
502        match self {
503            Value::Null => ValueKind::Null,
504            Value::True | Value::False => ValueKind::Bool,
505            Value::String(_) => ValueKind::String,
506            Value::Number(_) => ValueKind::Number,
507            Value::Array(_) => ValueKind::Array,
508            Value::Object(_) => ValueKind::Object,
509        }
510    }
511
512    pub(crate) fn is_null(&self) -> bool {
513        matches!(self, Value::Null)
514    }
515
516    /// Return true if the `Value` can't contain child elements.
517    pub(crate) fn is_scalar(&self) -> bool {
518        matches!(
519            self,
520            Value::Null | Value::True | Value::False | Value::String(_) | Value::Number(_)
521        )
522    }
523
524    pub(crate) fn as_array(&self) -> Option<&[Element<'buf>]> {
525        match self {
526            Value::Array(elems) => Some(elems),
527            _ => None,
528        }
529    }
530
531    pub(crate) fn as_number(&self) -> Option<&str> {
532        match self {
533            Value::Number(s) => Some(s),
534            _ => None,
535        }
536    }
537
538    /// Return `Some(&str)` if the `Value` is a `String`.
539    pub(crate) fn to_raw_str(&self) -> Option<RawStr<'buf>> {
540        match self {
541            Value::String(s) => Some(*s),
542            _ => None,
543        }
544    }
545
546    /// Return `Some(&[Field])` if the `Value` is a `Object`.
547    pub(crate) fn as_object_fields(&self) -> Option<&[Field<'buf>]> {
548        match self {
549            Value::Object(fields) => Some(fields),
550            _ => None,
551        }
552    }
553}
554
555impl fmt::Display for Value<'_> {
556    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
557        match self {
558            Self::Null => write!(f, "null"),
559            Self::True => write!(f, "true"),
560            Self::False => write!(f, "false"),
561            Self::String(s) => write!(f, "{s}"),
562            Self::Number(s) => write!(f, "{s}"),
563            Self::Array(..) => f.write_str("[...]"),
564            Self::Object(..) => f.write_str("{...}"),
565        }
566    }
567}
568
569/// A light-weight type identity for a JSON `Value`'s content.
570#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
571pub enum ValueKind {
572    Null,
573    Bool,
574    Number,
575    String,
576    Array,
577    Object,
578}
579
580impl fmt::Display for ValueKind {
581    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
582        match self {
583            ValueKind::Null => write!(f, "null"),
584            ValueKind::Bool => write!(f, "bool"),
585            ValueKind::Number => write!(f, "number"),
586            ValueKind::String => write!(f, "string"),
587            ValueKind::Array => write!(f, "array"),
588            ValueKind::Object => write!(f, "object"),
589        }
590    }
591}
592
593/// Used to distinguish the type of compound object.
594///
595/// This is used to track which type of object an `Element` is in when parsing.
596#[derive(Copy, Clone, Debug, Eq, PartialEq)]
597pub(crate) enum ObjectKind {
598    Object,
599    Array,
600}
601
602pub type RawMap<'buf> = BTreeMap<RawStr<'buf>, Element<'buf>>;
603pub type RawRefMap<'a, 'buf> = BTreeMap<RawStr<'buf>, &'a Element<'buf>>;
604
605#[expect(dead_code, reason = "pending use in `tariff::lint`")]
606pub(crate) trait FieldsIntoExt<'buf> {
607    fn into_map(self) -> RawMap<'buf>;
608}
609
610pub(crate) trait FieldsAsExt<'buf> {
611    fn as_raw_map(&self) -> RawRefMap<'_, 'buf>;
612    fn find_field(&self, key: &str) -> Option<&Field<'buf>>;
613}
614
615impl<'buf> FieldsIntoExt<'buf> for Vec<Field<'buf>> {
616    fn into_map(self) -> RawMap<'buf> {
617        self.into_iter()
618            .map(|field| (field.key(), field.into_element()))
619            .collect()
620    }
621}
622
623impl<'buf> FieldsAsExt<'buf> for Vec<Field<'buf>> {
624    fn as_raw_map(&self) -> RawRefMap<'_, 'buf> {
625        self.iter()
626            .map(|field| (field.key(), field.element()))
627            .collect()
628    }
629
630    fn find_field(&self, key: &str) -> Option<&Field<'buf>> {
631        self.iter().find(|field| field.key().as_raw() == key)
632    }
633}
634
635impl<'buf> FieldsAsExt<'buf> for [Field<'buf>] {
636    fn as_raw_map(&self) -> RawRefMap<'_, 'buf> {
637        self.iter()
638            .map(|field| (field.key(), field.element()))
639            .collect()
640    }
641
642    fn find_field(&self, key: &str) -> Option<&Field<'buf>> {
643        self.iter().find(|field| field.key().as_raw() == key)
644    }
645}
646
647/// A collection of paths that were unexpected according to the schema used while parsing the JSON
648/// for an OCPI object.
649#[derive(Clone, Debug)]
650pub struct UnexpectedFields<'buf>(Vec<PathNodeRef<'buf>>);
651
652impl fmt::Display for UnexpectedFields<'_> {
653    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
654        if f.alternate() {
655            // Print each path on a newline.
656            f.write_str("[\n")?;
657            for entry in &self.0 {
658                writeln!(f, "\t\"{entry}\",")?;
659            }
660            f.write_str("]\n")?;
661        } else {
662            // Print all paths on a single line.
663            f.write_char('[')?;
664            for entry in &self.0 {
665                write!(f, "{entry},")?;
666            }
667            f.write_char(']')?;
668        }
669
670        Ok(())
671    }
672}
673
674impl<'buf> UnexpectedFields<'buf> {
675    /// Create an empty `UnexpectedFields` collection.
676    pub(crate) fn empty() -> Self {
677        Self(vec![])
678    }
679
680    /// Create a collection of `UnexpectedFields` from a `Vec`
681    pub(crate) fn from_vec(v: Vec<PathNodeRef<'buf>>) -> Self {
682        Self(v)
683    }
684
685    /// Return the field paths as a `Vec` of `String`s.
686    pub fn to_strings(&self) -> Vec<String> {
687        self.0.iter().map(ToString::to_string).collect()
688    }
689
690    /// Return the field paths as a `Vec` of `String`s.
691    pub fn into_strings(self) -> Vec<String> {
692        self.0.into_iter().map(|path| path.to_string()).collect()
693    }
694
695    /// Return true if the list of unexpected fields is empty.
696    pub fn is_empty(&self) -> bool {
697        self.0.is_empty()
698    }
699
700    /// Return the number of unexpected fields.
701    pub fn len(&self) -> usize {
702        self.0.len()
703    }
704
705    /// Return an Iterator over the unexpected fields.
706    pub fn iter<'a>(&'a self) -> UnexpectedFieldsIter<'a, 'buf> {
707        UnexpectedFieldsIter(self.0.iter())
708    }
709}
710
711impl<'buf> IntoIterator for UnexpectedFields<'buf> {
712    type Item = PathRef<'buf>;
713
714    type IntoIter = UnexpectedFieldsIntoIter<'buf>;
715
716    fn into_iter(self) -> Self::IntoIter {
717        UnexpectedFieldsIntoIter(self.0.into_iter())
718    }
719}
720
721pub struct UnexpectedFieldsIntoIter<'buf>(std::vec::IntoIter<PathNodeRef<'buf>>);
722
723impl<'buf> Iterator for UnexpectedFieldsIntoIter<'buf> {
724    type Item = PathRef<'buf>;
725
726    fn next(&mut self) -> Option<Self::Item> {
727        let path_node = self.0.next()?;
728
729        Some(PathRef(path_node))
730    }
731}
732
733impl<'a, 'buf> IntoIterator for &'a UnexpectedFields<'buf> {
734    type Item = PathRef<'buf>;
735
736    type IntoIter = UnexpectedFieldsIter<'a, 'buf>;
737
738    fn into_iter(self) -> Self::IntoIter {
739        self.iter()
740    }
741}
742
743/// An `Iterator` over each unexpected field as a `PathRef`.
744pub struct UnexpectedFieldsIter<'a, 'buf>(std::slice::Iter<'a, PathNodeRef<'buf>>);
745
746impl<'buf> Iterator for UnexpectedFieldsIter<'_, 'buf> {
747    type Item = PathRef<'buf>;
748
749    fn next(&mut self) -> Option<Self::Item> {
750        let path_node = self.0.next()?;
751
752        Some(PathRef(Arc::clone(path_node)))
753    }
754}
755
756/// A path to a JSON `Element` where the path components are borrowed from the source JSON `&str`.
757///
758/// The Display impl outputs strings like:
759///
760/// - `$` The root is represented by a dollar.
761/// - `$.object_key` Dots separate the path elements.
762/// - `$.object_key.2` Arrays are represented as integers.
763pub struct PathRef<'buf>(PathNodeRef<'buf>);
764
765impl fmt::Debug for PathRef<'_> {
766    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
767        write!(f, "{self}")
768    }
769}
770
771impl<'buf> PathRef<'buf> {
772    /// Return an [`Iterator`] over the components of this path.
773    pub fn components(&self) -> PathComponents<'buf> {
774        PathComponents(PathIter::new(Arc::clone(&self.0)))
775    }
776}
777
778/// An [`Iterator`] over the components of a path.
779pub struct PathComponents<'buf>(PathIter<'buf>);
780
781impl<'buf> Iterator for PathComponents<'buf> {
782    type Item = PathComponent<'buf>;
783
784    fn next(&mut self) -> Option<Self::Item> {
785        let path_node = self.0.next()?;
786        Some(PathComponent(path_node))
787    }
788}
789
790/// The `PathRef` can be compared with other strings just like a `String`.
791impl PartialEq<&str> for PathRef<'_> {
792    fn eq(&self, other: &&str) -> bool {
793        match_path_node(&self.0, other, |_| false)
794    }
795}
796
797/// The `PathRef` can be compared with other strings just like a `String`.
798impl PartialEq<String> for PathRef<'_> {
799    fn eq(&self, other: &String) -> bool {
800        match_path_node(&self.0, other, |_| false)
801    }
802}
803
804impl fmt::Display for PathRef<'_> {
805    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
806        fmt::Display::fmt(&self.0, f)
807    }
808}
809
810/// The path to a JSON `Element`.
811pub(crate) type PathNodeRef<'buf> = Arc<PathNode<'buf>>;
812
813/// A single node of a complete path.
814///
815/// Path's are structured as a linked list from the leaf of the path back to the root through the parents.
816///
817/// The Display impl of the `Path` outputs strings like:
818///
819/// - `$` The root is represented by a dollar.
820/// - `$.object_key` Dots separate the path elements.
821/// - `$.object_key.2` Arrays are represented as integers.
822#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
823pub(crate) enum PathNode<'buf> {
824    /// The root of the JSON `Element` tree.
825    #[default]
826    Root,
827    /// An `Array` element referenced by index.
828    Array {
829        parent: PathNodeRef<'buf>,
830        index: usize,
831    },
832    /// An `Object` field referenced be key value.
833    Object {
834        parent: PathNodeRef<'buf>,
835        key: RawStr<'buf>,
836    },
837}
838
839/// A lightweight enum used to indicate the kind of component being visited when using the
840/// [`PathComponents`] [`Iterator`].
841pub enum PathNodeKind {
842    /// The root of the JSON `Element` tree.
843    Root,
844    /// An `Array` element referenced by index.
845    Array,
846    /// An `Object` field referenced be key value.
847    Object,
848}
849
850/// A path to a JSON `Element` where the path components are heap allocated and so do not require
851/// a lifetime back to the source JSON `&str`.
852///
853/// The Display impl outputs strings like:
854///
855/// - `$` The root is represented by a dollar.
856/// - `$.object_key` Dots separate the path elements.
857/// - `$.object_key.2` Arrays are represented as integers.
858#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
859pub struct Path(Vec<PathPiece>);
860
861impl Path {
862    /// Create a root `Path`.
863    const fn root() -> Self {
864        Self(vec![])
865    }
866
867    /// Create an `Path` by iterating over a [`PathNode`].
868    fn from_node(path: PathNodeRef<'_>) -> Self {
869        let paths: Vec<_> = PathIter::new(path).collect();
870
871        let pieces = paths
872            .into_iter()
873            .rev()
874            .filter_map(|path_node| match *path_node {
875                PathNode::Root => None,
876                PathNode::Array { index, .. } => Some(PathPiece::Array(index)),
877                PathNode::Object { key, .. } => Some(PathPiece::Object(key.to_string())),
878            })
879            .collect();
880
881        Self(pieces)
882    }
883}
884
885/// The `Path` can be compared with other strings just like a `String`.
886impl PartialEq<&str> for Path {
887    fn eq(&self, other: &&str) -> bool {
888        match_path(self, other)
889    }
890}
891
892/// The `Path` can be compared with other strings just like a `String`.
893impl PartialEq<String> for Path {
894    fn eq(&self, other: &String) -> bool {
895        match_path(self, other)
896    }
897}
898
899impl fmt::Display for Path {
900    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
901        let iter = self.0.iter();
902
903        write!(f, "$")?;
904
905        for path in iter {
906            write!(f, ".{path}")?;
907        }
908
909        Ok(())
910    }
911}
912
913/// A piece/component of a [`Path`].
914///
915/// The `PathComponent` name is already taken and this type is private.
916#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
917enum PathPiece {
918    /// An `Array` element referenced by index.
919    Array(usize),
920    /// An `Object` field referenced be key value.
921    Object(String),
922}
923
924impl fmt::Display for PathPiece {
925    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
926        match self {
927            PathPiece::Array(index) => write!(f, "{index}"),
928            PathPiece::Object(key) => write!(f, "{key}"),
929        }
930    }
931}
932
933/// A single component of a [`PathRef`].
934pub struct PathComponent<'buf>(PathNodeRef<'buf>);
935
936impl PathComponent<'_> {
937    /// Return the kind of component this is.
938    pub fn kind(&self) -> PathNodeKind {
939        match *self.0 {
940            PathNode::Root => PathNodeKind::Root,
941            PathNode::Array { .. } => PathNodeKind::Array,
942            PathNode::Object { .. } => PathNodeKind::Object,
943        }
944    }
945}
946
947impl fmt::Display for PathComponent<'_> {
948    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
949        match *self.0 {
950            PathNode::Root => f.write_str(PATH_ROOT),
951            PathNode::Array { index, .. } => write!(f, "{index}"),
952            PathNode::Object { key, .. } => write!(f, "{key}"),
953        }
954    }
955}
956
957impl fmt::Display for PathNode<'_> {
958    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
959        let paths: Vec<_> = PathIter::new(Arc::new(self.clone())).collect();
960        let mut iter = paths.into_iter().rev();
961
962        if f.alternate() {
963            // Print out each path element as a debugging tab-stop.
964            for path in iter {
965                match *path {
966                    PathNode::Root => f.write_str("")?,
967                    PathNode::Array { .. } | PathNode::Object { .. } => f.write_str("...|")?,
968                }
969            }
970        } else {
971            if let Some(path) = iter.next() {
972                write!(f, "{}", PathComponent(path))?;
973            }
974
975            for path in iter {
976                write!(f, ".{}", PathComponent(path))?;
977            }
978        }
979        Ok(())
980    }
981}
982
983impl<'buf> PathNode<'buf> {
984    /// Returns true if the `Path` refers to the root.
985    pub(crate) fn is_root(&self) -> bool {
986        matches!(self, PathNode::Root)
987    }
988
989    /// Returns true if the `Path` refers to an `Array`.
990    pub(crate) fn is_array(&self) -> bool {
991        matches!(self, PathNode::Array { .. })
992    }
993
994    /// Return a key as `Some(&str)` if the `Path` refers to an `Object`.
995    pub(crate) fn as_object_key(&self) -> Option<&RawStr<'buf>> {
996        match self {
997            PathNode::Object { key, .. } => Some(key),
998            PathNode::Root | PathNode::Array { .. } => None,
999        }
1000    }
1001}
1002
1003/// Return true if the given `PathNode` matches the given `&str`.
1004///
1005/// If the `skip` function returns true, that path component is skipped.
1006/// The `skip` function allows this single function to implement comparisons between `PathNode` and `&str`;
1007/// and comparisons between `PathNode` and `PathGlob`.
1008fn match_path_node<F>(path: &PathNode<'_>, s: &str, mut skip: F) -> bool
1009where
1010    F: FnMut(&str) -> bool,
1011{
1012    let mut parts = s.rsplit(PATH_SEPARATOR);
1013    let mut paths_iter = PathIter::new(Arc::new(path.clone()));
1014
1015    loop {
1016        let node_segment = paths_iter.next();
1017        let str_segment = parts.next();
1018
1019        let (node_segment, str_segment) = match (node_segment, str_segment) {
1020            // If we have exhausted both iterators then the `&str` is equal to the path.
1021            (None, None) => return true,
1022            // If either of the iterators are a different size, then they don't match.
1023            (None, Some(_)) | (Some(_), None) => return false,
1024            // If both iterators have another item, continue on to try match them.
1025            (Some(a), Some(b)) => (a, b),
1026        };
1027
1028        // If the skip function says to skip a path segment, then continue to the next segment.
1029        if skip(str_segment) {
1030            continue;
1031        }
1032
1033        let yip = match *node_segment {
1034            PathNode::Root => str_segment == PATH_ROOT,
1035            PathNode::Array { index, .. } => {
1036                let Ok(b) = str_segment.parse::<usize>() else {
1037                    return false;
1038                };
1039
1040                index == b
1041            }
1042            PathNode::Object { key, .. } => key.as_raw() == str_segment,
1043        };
1044
1045        // Return false on the first mismatch.
1046        if !yip {
1047            return false;
1048        }
1049    }
1050}
1051
1052/// Return true if the given `Path` matches the given `&str`.
1053fn match_path(path: &Path, s: &str) -> bool {
1054    let mut parts = s.split(PATH_SEPARATOR);
1055    let mut paths_iter = path.0.iter();
1056
1057    let Some(str_segment) = parts.next() else {
1058        return false;
1059    };
1060
1061    // The root path segment is not explicitly stored in a `Path` so we just match the first
1062    // `str` segment to the expected `$` nomenclature.
1063    if str_segment != PATH_ROOT {
1064        return false;
1065    }
1066
1067    loop {
1068        let node_segment = paths_iter.next();
1069        let str_segment = parts.next();
1070
1071        let (node_segment, str_segment) = match (node_segment, str_segment) {
1072            // If we have exhausted both iterators then the `&str` is equal to the path.
1073            (None, None) => return true,
1074            // If either of the iterators are a different size, then they don't match.
1075            (None, Some(_)) | (Some(_), None) => return false,
1076            // If both iterators have another item, continue on to try match them.
1077            (Some(a), Some(b)) => (a, b),
1078        };
1079
1080        let yip = match node_segment {
1081            PathPiece::Array(index) => {
1082                let Ok(b) = str_segment.parse::<usize>() else {
1083                    return false;
1084                };
1085
1086                *index == b
1087            }
1088            PathPiece::Object(key) => key == str_segment,
1089        };
1090
1091        // Return false on the first mismatch.
1092        if !yip {
1093            return false;
1094        }
1095    }
1096}
1097
1098impl PartialEq<&str> for PathNode<'_> {
1099    fn eq(&self, other: &&str) -> bool {
1100        match_path_node(self, other, |_| false)
1101    }
1102}
1103
1104impl PartialEq<String> for PathNode<'_> {
1105    fn eq(&self, other: &String) -> bool {
1106        match_path_node(self, other, |_| false)
1107    }
1108}
1109
1110/// Traverse a `Path` from the leaf to the root.
1111struct PathIter<'buf> {
1112    /// The root has been reached.
1113    complete: bool,
1114    /// The current path node to introspect when `Iterator::next` is called.
1115    path: PathNodeRef<'buf>,
1116}
1117
1118impl<'buf> PathIter<'buf> {
1119    /// Create a new `PathIter` from a leaf node.
1120    fn new(path: PathNodeRef<'buf>) -> Self {
1121        Self {
1122            complete: false,
1123            path,
1124        }
1125    }
1126}
1127
1128impl<'buf> Iterator for PathIter<'buf> {
1129    type Item = PathNodeRef<'buf>;
1130
1131    fn next(&mut self) -> Option<Self::Item> {
1132        if self.complete {
1133            return None;
1134        }
1135
1136        match &*self.path {
1137            PathNode::Root => {
1138                // The iteration is complete once we've arrived at the root node.
1139                self.complete = true;
1140                Some(Arc::clone(&self.path))
1141            }
1142            PathNode::Array { parent, .. } | PathNode::Object { parent, .. } => {
1143                let next = Arc::clone(&self.path);
1144                self.path = Arc::clone(parent);
1145                Some(next)
1146            }
1147        }
1148    }
1149}
1150
1151/// Display the expectation stack for debugging
1152struct DisplayExpectStack<'a>(&'a [schema::Expect]);
1153
1154impl fmt::Display for DisplayExpectStack<'_> {
1155    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1156        let mut iter = self.0.iter().rev();
1157        let last = iter.next();
1158
1159        // Use the `~` to represent a schema stack.
1160        f.write_str("~")?;
1161
1162        for _ in iter {
1163            f.write_str("...~")?;
1164        }
1165
1166        if let Some(exp) = last {
1167            match exp {
1168                schema::Expect::Scalar => f.write_str("~")?,
1169                schema::Expect::Array(element) => match &**element {
1170                    schema::Element::Scalar => f.write_str("~")?,
1171                    schema::Element::Array(element) => write!(f, "[{element:?}]")?,
1172                    schema::Element::Object(fields) => {
1173                        write!(f, "[{{{:}}}])", DisplayExpectFields(&**fields))?;
1174                    }
1175                },
1176                schema::Expect::Object(fields) => {
1177                    write!(f, "{{{:}}}", DisplayExpectFields(&**fields))?;
1178                }
1179                schema::Expect::UnmatchedScalar => write!(f, "unmatched(scalar)")?,
1180                schema::Expect::UnmatchedArray => write!(f, "unmatched(array)")?,
1181                schema::Expect::UnmatchedObject => write!(f, "unmatched(object)")?,
1182                schema::Expect::OutOfSchema => write!(f, "no_schema")?,
1183            }
1184        }
1185
1186        Ok(())
1187    }
1188}
1189
1190/// Display the fields of a schema expect stack level.
1191struct DisplayExpectFields<'a, V>(&'a BTreeMap<&'a str, V>);
1192
1193impl<V> fmt::Display for DisplayExpectFields<'_, V> {
1194    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1195        const MAX_FIELDS: usize = 8;
1196
1197        let mut count = 0;
1198        let mut iter = self.0.keys().peekable();
1199
1200        loop {
1201            if count >= MAX_FIELDS {
1202                f.write_str("...")?;
1203                break;
1204            }
1205
1206            let Some(field) = iter.next() else {
1207                break;
1208            };
1209
1210            let Some(n) = count.checked_add(1) else {
1211                break;
1212            };
1213            count = n;
1214
1215            write!(f, "{field}")?;
1216
1217            let Some(_) = iter.peek() else {
1218                break;
1219            };
1220
1221            f.write_str(", ")?;
1222        }
1223
1224        Ok(())
1225    }
1226}
1227
1228#[derive(Debug)]
1229struct UnbalancedExpectStack;
1230
1231impl fmt::Display for UnbalancedExpectStack {
1232    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1233        f.write_str("unbalanced expectation stack")
1234    }
1235}
1236
1237impl std::error::Error for UnbalancedExpectStack {}
1238
1239/// Parse the JSON into a [`ParseReport`] checking the parsed [`Element`]s names against the given
1240/// [`schema`] and reporting fields that are unexpected in the [`ParseReport::unexpected_fields`].
1241pub(crate) fn parse_with_schema<'buf>(
1242    json: &'buf str,
1243    schema: &schema::Element,
1244) -> Result<ParseReport<'buf>, Error> {
1245    let parser = Parser::new(json);
1246    let mut unexpected_fields = vec![];
1247    // The current node of the schema is the last element of this `Vec`.
1248    let mut expectation_stack = vec![schema.to_expectation()];
1249
1250    for event in parser {
1251        match event? {
1252            parser::Event::Open { kind, parent_path } => {
1253                // Take the schema expectation off the stack.
1254                // This is simpler than taking a `&mut` to the last element.
1255                let Some(expectation) = expectation_stack.pop() else {
1256                    return Err(ErrorKind::Internal(Box::new(UnbalancedExpectStack))
1257                        .into_partial_error_without_token()
1258                        .with_root_path());
1259                };
1260
1261                if tracing::enabled!(Level::DEBUG) {
1262                    match kind {
1263                        ObjectKind::Array => {
1264                            trace!("{parent_path} [ {}", DisplayExpectStack(&expectation_stack));
1265                        }
1266                        ObjectKind::Object => trace!(
1267                            "{parent_path} {{ {}",
1268                            DisplayExpectStack(&expectation_stack)
1269                        ),
1270                    }
1271                }
1272
1273                match expectation {
1274                    schema::Expect::Array(elem) => {
1275                        // If the opening element is at the root we only care if the element
1276                        // is an array or not.
1277                        if parent_path.is_root() {
1278                            let next = match kind {
1279                                ObjectKind::Array => schema::Expect::Array(elem),
1280                                ObjectKind::Object => schema::Expect::UnmatchedArray,
1281                            };
1282
1283                            expectation_stack.push(next);
1284                            trace!("{}", DisplayExpectStack(&expectation_stack));
1285                            continue;
1286                        }
1287
1288                        if !parent_path.is_array() {
1289                            expectation_stack.push(schema::Expect::UnmatchedArray);
1290                            trace!("{}", DisplayExpectStack(&expectation_stack));
1291                            continue;
1292                        }
1293
1294                        expectation_stack.push(schema::Expect::Array(Arc::clone(&elem)));
1295                        // Each array element should match this expectation
1296                        expectation_stack.push(elem.to_expectation());
1297                    }
1298                    schema::Expect::Object(fields) => {
1299                        // If the opening element is at the root there is no path to inspect.
1300                        // We only care if the element is an object or not.
1301                        if parent_path.is_root() {
1302                            let next = match kind {
1303                                ObjectKind::Array => schema::Expect::UnmatchedObject,
1304                                ObjectKind::Object => schema::Expect::Object(fields),
1305                            };
1306
1307                            expectation_stack.push(next);
1308                            trace!("{}", DisplayExpectStack(&expectation_stack));
1309                            continue;
1310                        }
1311                        let Some(key) = parent_path.as_object_key() else {
1312                            expectation_stack.push(schema::Expect::UnmatchedObject);
1313                            trace!("{}", DisplayExpectStack(&expectation_stack));
1314                            continue;
1315                        };
1316
1317                        let next = if let Some(elem) = fields.get(key.as_raw()) {
1318                            open_object(kind, elem.as_ref())
1319                        } else {
1320                            unexpected_fields.push(parent_path);
1321                            schema::Expect::OutOfSchema
1322                        };
1323
1324                        expectation_stack.push(schema::Expect::Object(fields));
1325                        expectation_stack.push(next);
1326                    }
1327                    schema::Expect::OutOfSchema => {
1328                        // If we're already outside of the schema we put that back on the stack
1329                        // and add a new one for the object that just opened.
1330                        //
1331                        // We need to track the object level even though the schema expectations
1332                        // have been exhausted, as we'll pop these placeholder `OutOfSchema`s
1333                        // off the stack when the object has closed so we land on the correct
1334                        // schema again.
1335                        expectation_stack.push(expectation);
1336                        expectation_stack.push(schema::Expect::OutOfSchema);
1337                    }
1338                    schema::Expect::UnmatchedArray | schema::Expect::UnmatchedObject => {
1339                        expectation_stack.push(expectation);
1340                        expectation_stack.push(schema::Expect::OutOfSchema);
1341                    }
1342                    _ => {
1343                        expectation_stack.push(expectation);
1344                    }
1345                }
1346
1347                trace!("{}", DisplayExpectStack(&expectation_stack));
1348            }
1349            parser::Event::Element { kind, parent_path } => {
1350                // Take the schema expectation off the stack.
1351                // This is simpler than taking a `&mut` to the last element.
1352                let Some(expectation) = expectation_stack.pop() else {
1353                    return Err(ErrorKind::Internal(Box::new(UnbalancedExpectStack))
1354                        .into_partial_error_without_token()
1355                        .with_root_path());
1356                };
1357
1358                // An `Element` of kind `Array` or `Object` means the `Element` is closed
1359                // and has completed construction. The expectation can remain off the stack.
1360                if let ValueKind::Array | ValueKind::Object = kind {
1361                    if tracing::enabled!(Level::DEBUG) {
1362                        match kind {
1363                            ValueKind::Array => {
1364                                trace!(
1365                                    "{parent_path} ] {}",
1366                                    DisplayExpectStack(&expectation_stack)
1367                                );
1368                            }
1369                            ValueKind::Object => trace!(
1370                                "{parent_path} }} {}",
1371                                DisplayExpectStack(&expectation_stack)
1372                            ),
1373                            _ => (),
1374                        }
1375                    }
1376                    continue;
1377                }
1378
1379                match expectation {
1380                    #[expect(
1381                        clippy::unreachable,
1382                        reason = "The parser only emits an `Event::Complete` for a scalar object at the root"
1383                    )]
1384                    schema::Expect::Object(fields) => match &*parent_path {
1385                        PathNode::Root => unreachable!(),
1386                        PathNode::Array { .. } => {
1387                            expectation_stack.push(schema::Expect::UnmatchedObject);
1388                        }
1389                        PathNode::Object { parent, key } => {
1390                            trace!("{parent:#}.{key}");
1391
1392                            if !fields.contains_key(key.as_raw()) {
1393                                unexpected_fields.push(parent_path);
1394                            }
1395
1396                            expectation_stack.push(schema::Expect::Object(fields));
1397                        }
1398                    },
1399                    schema::Expect::OutOfSchema => {
1400                        unexpected_fields.push(parent_path);
1401                        expectation_stack.push(expectation);
1402                    }
1403                    _ => {
1404                        expectation_stack.push(expectation);
1405                    }
1406                }
1407            }
1408            parser::Event::Complete(element) => {
1409                if element.value().is_scalar() {
1410                    unexpected_fields.push(element.path_node());
1411                }
1412
1413                // Parsing the JSON is complete.
1414                // Return the `Element` and the unexpected fields collected during parsing
1415                return Ok(ParseReport {
1416                    element,
1417                    unexpected_fields: UnexpectedFields::from_vec(unexpected_fields),
1418                });
1419            }
1420        }
1421    }
1422
1423    Err(ErrorKind::UnexpectedEOF
1424        .into_partial_error_without_token()
1425        .with_root_path())
1426}
1427
1428fn open_object(kind: ObjectKind, elem: Option<&Arc<schema::Element>>) -> schema::Expect {
1429    let Some(schema) = elem else {
1430        return schema::Expect::OutOfSchema;
1431    };
1432
1433    match (kind, &**schema) {
1434        (ObjectKind::Object | ObjectKind::Array, schema::Element::Scalar) => {
1435            schema::Expect::UnmatchedScalar
1436        }
1437        (ObjectKind::Object, schema::Element::Array(_)) => schema::Expect::UnmatchedArray,
1438        (ObjectKind::Object, schema::Element::Object(fields)) => {
1439            schema::Expect::Object(Arc::clone(fields))
1440        }
1441        (ObjectKind::Array, schema::Element::Array(element)) => {
1442            schema::Expect::Array(Arc::clone(element))
1443        }
1444        (ObjectKind::Array, schema::Element::Object(_)) => schema::Expect::UnmatchedObject,
1445    }
1446}
1447
1448/// The output of the `parse_with_schema` function where the parsed JSON `Element` is returned
1449/// along with a list of fields that the schema did not define.
1450#[derive(Debug)]
1451pub(crate) struct ParseReport<'buf> {
1452    /// The root JSON [`Element`].
1453    pub element: Element<'buf>,
1454
1455    /// A list of fields that were not expected: The schema did not define them.
1456    pub unexpected_fields: UnexpectedFields<'buf>,
1457}