Skip to main content

granit_parser/
parser.rs

1//! Home to the YAML Parser.
2//!
3//! The parser takes input from the [`crate::scanner::Scanner`], performs final checks for YAML
4//! compliance, and emits a stream of YAML events. This stream can for instance be used to create
5//! YAML objects.
6
7use crate::{
8    error::{ErrorKind, ScanError},
9    input::{str::StrInput, BorrowedInput},
10    scanner::{Marker, Placement, QueuedToken, QueuedTokenType, ScalarStyle, Scanner, Span},
11    BufferedInput, FallibleBufferedInput, Options,
12};
13
14use alloc::{
15    borrow::Cow,
16    collections::{BTreeMap, BTreeSet, VecDeque},
17    string::{String, ToString},
18    vec::Vec,
19};
20use core::{
21    convert::Infallible,
22    fmt::{self, Display},
23};
24
25#[derive(Clone, Copy, PartialEq, Debug, Eq)]
26enum State {
27    StreamStart,
28    ImplicitDocumentStart,
29    DocumentStart,
30    DocumentContent,
31    DocumentEnd,
32    BlockNode,
33    BlockNodeOrIndentlessSequence,
34    FlowNode,
35    BlockSequenceFirstEntry,
36    BlockSequenceEntry,
37    IndentlessSequenceEntry,
38    IndentlessSequenceEntryNode,
39    BlockMappingFirstKey,
40    BlockMappingKey,
41    BlockMappingKeyNode,
42    BlockMappingValue,
43    BlockMappingValueNode,
44    FlowSequenceFirstEntry,
45    FlowSequenceEntry,
46    FlowSequenceEntryMappingKey,
47    FlowSequenceEntryMappingValue,
48    FlowSequenceEntryMappingValueNode,
49    FlowSequenceEntryMappingEnd,
50    FlowMappingFirstKey,
51    FlowMappingKey,
52    FlowMappingKeyNode,
53    FlowMappingValue,
54    FlowMappingValueNode,
55    FlowMappingEmptyValue,
56    BlockSequenceEntryNode,
57    End,
58}
59
60/// YAML version declared by a `%YAML` directive.
61#[derive(Copy, Clone, PartialEq, Debug, Eq, Hash)]
62pub struct YamlVersion {
63    /// Major version number.
64    pub major: u32,
65    /// Minor version number.
66    pub minor: u32,
67}
68
69impl YamlVersion {
70    /// Create a YAML version value.
71    #[must_use]
72    pub const fn new(major: u32, minor: u32) -> Self {
73        Self { major, minor }
74    }
75}
76
77/// An event generated by the YAML parser.
78///
79/// Events are used in the low-level event-based API (push parser). The API entrypoint is the
80/// [`EventReceiver`] trait.
81#[non_exhaustive]
82#[derive(Clone, PartialEq, Debug, Eq)]
83pub enum Event<'input> {
84    /// Event generated at the very beginning of parsing.
85    StreamStart,
86    /// Last event that will be generated by the parser. Signals EOF.
87    StreamEnd,
88    /// The start of a YAML document.
89    ///
90    DocumentStart(
91        /// Whether this is an explicit document start marker (`---`).
92        ///
93        /// When `false`, the document start is implicit.
94        bool,
95        /// YAML version declared by a preceding `%YAML` directive, if any.
96        Option<YamlVersion>,
97    ),
98    /// The end of a YAML document.
99    ///
100    /// This event is emitted for both explicit document end markers (`...`) and implicit document
101    /// ends.
102    DocumentEnd,
103    /// A YAML alias.
104    Alias(
105        /// The anchor ID the alias refers to.
106        usize,
107    ),
108    /// A YAML source comment.
109    ///
110    /// Comments are presentation metadata, not YAML data nodes. The payload is the raw text
111    /// exactly after `#`, excluding only the line break. The placement is a best-effort hint for
112    /// correlating the comment with nearby YAML presentation. The companion parser [`Span`] covers
113    /// the whole source comment, including `#` and excluding the line break.
114    Comment(
115        /// Raw comment payload exactly after `#`, excluding only the line break.
116        Cow<'input, str>,
117        /// Best-effort placement relative to nearby YAML content.
118        Placement,
119    ),
120    /// A YAML scalar value.
121    Scalar(
122        /// The scalar value after YAML escape processing.
123        Cow<'input, str>,
124        /// The source notation used for the scalar.
125        ScalarStyle,
126        /// The anchor ID defined on this scalar, or `0` if it has no anchor.
127        usize,
128        /// The resolved tag attached to this scalar, if any.
129        Option<Cow<'input, Tag>>,
130    ),
131    /// The start of a YAML sequence (array).
132    SequenceStart(
133        /// The notation style used for the sequence.
134        StructureStyle,
135        /// The anchor ID defined on this sequence, or `0` if it has no anchor.
136        usize,
137        /// The resolved tag attached to this sequence, if any.
138        Option<Cow<'input, Tag>>,
139    ),
140    /// The end of a YAML sequence (array).
141    SequenceEnd,
142    /// The start of a YAML mapping (object, hash).
143    MappingStart(
144        /// The notation style used for the mapping (Flow or Block).
145        StructureStyle,
146        /// The anchor ID defined on this mapping, or `0` if it has no anchor.
147        usize,
148        /// The resolved tag attached to this mapping, if any.
149        Option<Cow<'input, Tag>>,
150    ),
151    /// The end of a YAML mapping (object, hash).
152    MappingEnd,
153}
154
155/// The notation style used for a YAML sequence or mapping.
156///
157/// [`StructureStyle::Block`] means block notation:
158///
159/// ```yaml
160/// items:
161///   - milk
162///   - bread
163/// mapping:
164///   name: Ada
165///   active: true
166/// ```
167///
168/// [`StructureStyle::Flow`] means flow notation:
169///
170/// ```yaml
171/// items: [milk, bread]
172/// mapping: {name: Ada, active: true}
173/// ```
174#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)]
175pub enum StructureStyle {
176    /// Block notation, such as `- item` sequences and `key: value` mappings.
177    Block,
178    /// Flow notation, such as `[item]` sequences and `{key: value}` mappings.
179    Flow,
180}
181
182/// A YAML tag.
183#[derive(Clone, PartialEq, Debug, Eq, Ord, PartialOrd, Hash)]
184pub struct Tag {
185    /// Resolved tag handle or prefix.
186    ///
187    /// Examples include `tag:yaml.org,2002:` for core-schema tags and `!` for local tags.
188    handle: String,
189    /// Tag suffix following the resolved handle or prefix.
190    suffix: String,
191    /// Tag handle as written in the source before `%TAG` directive resolution.
192    ///
193    /// For example, with `%TAG !e! tag:example.com,2000:`, a source tag `!e!keep` is resolved
194    /// as `handle = "tag:example.com,2000:"` and `suffix = "keep"`, while
195    /// `original_handle = "!e!"`.
196    original_handle: String,
197}
198
199const YAML_CORE_SCHEMA_PREFIX: &str = "tag:yaml.org,2002:";
200
201// YAML 1.2.2 defines Core Schema tags by reference:
202// - §10.3.1 says Core Schema uses the same tags as YAML's JSON Schema.
203// - §10.2.1 adds null/bool/int/float to the Failsafe Schema.
204// - §10.1.1 defines the Failsafe Schema tags map/seq/str.
205// Therefore the YAML 1.2.2 Core Schema tag suffixes are:
206// bool, float, int, map, null, seq, and str.
207const YAML_CORE_SCHEMA_SUFFIXES: [&str; 7] = ["bool", "float", "int", "map", "null", "seq", "str"];
208
209fn known_yaml_core_schema_suffix(suffix: &str) -> Option<&str> {
210    YAML_CORE_SCHEMA_SUFFIXES
211        .contains(&suffix)
212        .then_some(suffix)
213}
214
215fn known_yaml_core_schema_suffix_from_split(
216    handle_tail: &str,
217    suffix: &str,
218) -> Option<&'static str> {
219    YAML_CORE_SCHEMA_SUFFIXES.iter().copied().find(|candidate| {
220        candidate
221            .strip_prefix(handle_tail)
222            .is_some_and(|candidate_tail| candidate_tail == suffix)
223    })
224}
225
226impl Tag {
227    /// Create a tag from resolved parts.
228    ///
229    /// This is mainly useful for tests and consumers constructing parser-compatible tags by hand.
230    /// When the original source handle matters, use [`Self::with_original_handle`].
231    #[must_use]
232    pub fn new(handle: impl Into<String>, suffix: impl Into<String>) -> Self {
233        let handle = handle.into();
234        Self {
235            original_handle: handle.clone(),
236            handle,
237            suffix: suffix.into(),
238        }
239    }
240
241    /// Create a tag from resolved parts and the handle as written in the source.
242    #[must_use]
243    pub fn with_original_handle(
244        handle: impl Into<String>,
245        suffix: impl Into<String>,
246        original_handle: impl Into<String>,
247    ) -> Self {
248        Self {
249            handle: handle.into(),
250            suffix: suffix.into(),
251            original_handle: original_handle.into(),
252        }
253    }
254
255    /// Return the resolved tag handle or prefix.
256    #[must_use]
257    pub fn handle(&self) -> &str {
258        &self.handle
259    }
260
261    /// Return the suffix following the resolved tag handle or prefix.
262    #[must_use]
263    pub fn suffix(&self) -> &str {
264        &self.suffix
265    }
266
267    /// Return the tag handle as written before `%TAG` directive resolution.
268    #[must_use]
269    pub fn original_handle(&self) -> &str {
270        &self.original_handle
271    }
272
273    /// Return the resolved YAML core-schema suffix for this tag, if it is a known core tag.
274    ///
275    /// The tag is matched by its resolved URI, not by the source handle spelling. For example,
276    /// `!!int`, `!<tag:yaml.org,2002:int>`, and a `%TAG` split such as
277    /// `%TAG !m! tag:yaml.org,2002:i` followed by `!m!nt` all return `Some("int")`.
278    ///
279    /// Authored tag parts are left unchanged; use [`Self::parts`], [`Self::original_parts`], or
280    /// [`Self::original`] to inspect those spellings.
281    #[must_use]
282    pub fn core_suffix(&self) -> Option<&str> {
283        // The handle ends at or before the namespace boundary. The remaining namespace
284        // prefix and the complete type name are both contained in `suffix`.
285        if let Some(remaining_prefix) = YAML_CORE_SCHEMA_PREFIX.strip_prefix(self.handle.as_str()) {
286            let suffix = self.suffix.strip_prefix(remaining_prefix)?;
287            return known_yaml_core_schema_suffix(suffix);
288        }
289
290        // The handle extends beyond the namespace boundary, so the type name is split
291        // between the end of `handle` and `suffix`. Compare against the seven fixed names
292        // directly instead of assembling an allocated String.
293        let handle_tail = self.handle.strip_prefix(YAML_CORE_SCHEMA_PREFIX)?;
294        known_yaml_core_schema_suffix_from_split(handle_tail, &self.suffix)
295    }
296
297    /// Return the type name this tag resolves to within `prefix`, or `None` outside it.
298    ///
299    /// Like [`Self::core_suffix`], the tag is matched by its resolved `handle ++ suffix` URI,
300    /// not the source spelling, so `!!omap`, `!<tag:yaml.org,2002:omap>`, and a `%TAG` split
301    /// such as `%TAG !o! tag:yaml.org,2002:o` then `!o!map` all resolve to `Some("omap")` for
302    /// the `tag:yaml.org,2002:` prefix — but the name is not limited to the seven core types.
303    ///
304    /// Borrows from `self`; allocates only when the handle extends past `prefix`.
305    #[must_use]
306    pub fn suffix_in_namespace(&self, prefix: &str) -> Option<Cow<'_, str>> {
307        if let Some(handle_tail) = self.handle.strip_prefix(prefix) {
308            // Handle spans the whole prefix; the name is its tail plus the suffix (the tail
309            // is empty unless a `%TAG` split pushed part of the name into the handle).
310            return Some(if handle_tail.is_empty() {
311                Cow::Borrowed(self.suffix.as_str())
312            } else {
313                let mut name = String::with_capacity(handle_tail.len() + self.suffix.len());
314                name.push_str(handle_tail);
315                name.push_str(&self.suffix);
316                Cow::Owned(name)
317            });
318        }
319
320        // Handle stops inside the prefix; the suffix supplies the rest of the prefix
321        // and then the name.
322        prefix
323            .strip_prefix(self.handle.as_str())
324            .and_then(|prefix_tail| self.suffix.strip_prefix(prefix_tail))
325            .map(Cow::Borrowed)
326    }
327
328    /// Returns whether the tag is a YAML tag from the core schema (`!!str`, `!!int`, ...).
329    ///
330    /// The YAML specification specifies [a list of
331    /// tags](https://yaml.org/spec/1.2.2/#103-core-schema) for the Core Schema. This function uses
332    /// the resolved tag URI, so it is independent of how the tag was split between handle and
333    /// suffix.
334    ///
335    /// # Return
336    /// Returns `true` if the resolved tag is a known YAML 1.2.2 Core Schema tag.
337    #[must_use]
338    pub fn is_yaml_core_schema(&self) -> bool {
339        self.core_suffix().is_some()
340    }
341
342    /// Return true for a YAML core-schema tag with the given suffix.
343    ///
344    /// For example, this matches core-schema tags such as `!!str`, `!!int`, `!!float`, `!!bool`,
345    /// `!!null`, `!!map`, or `!!seq` after tag resolution.
346    #[must_use]
347    pub fn is_yaml_core_schema_tag(&self, suffix: &str) -> bool {
348        self.core_suffix()
349            .is_some_and(|core_suffix| core_suffix == suffix)
350    }
351
352    /// Return true for a tag outside the YAML 1.2.2 Core Schema tag set.
353    ///
354    /// This checks the resolved tag URI, not just the tag handle spelling. For example,
355    /// `tag:yaml.org,2002:timestamp` is in the YAML tag namespace, but it is not a YAML 1.2.2
356    /// Core Schema tag.
357    #[must_use]
358    pub fn is_custom(&self) -> bool {
359        !self.is_yaml_core_schema()
360    }
361
362    /// Return the tag as `(handle, suffix)`.
363    #[must_use]
364    pub fn parts(&self) -> (&str, &str) {
365        (&self.handle, &self.suffix)
366    }
367
368    /// Return the tag as `(original_handle, suffix)` using the handle from the source token.
369    ///
370    /// This is useful when a consumer needs author spelling such as `!e!keep` instead of the
371    /// resolved URI tag `tag:example.com,2000:keep`.
372    #[must_use]
373    pub fn original_parts(&self) -> (&str, &str) {
374        (&self.original_handle, &self.suffix)
375    }
376
377    /// Return the tag spelling reconstructed from the source handle and suffix.
378    ///
379    /// For ordinary shorthand tags this returns the author-facing spelling, such as `!e!keep` or
380    /// `!!str`. For verbatim tags this returns a normalized verbatim spelling such as
381    /// `!<tag:example.com,2000:thing>`, not necessarily the byte-exact source token.
382    #[must_use]
383    pub fn original(&self) -> String {
384        if self.original_handle.is_empty() && self.suffix != "!" {
385            let mut tag = String::with_capacity(self.suffix.len() + 3);
386            tag.push_str("!<");
387            tag.push_str(&self.suffix);
388            tag.push('>');
389            return tag;
390        }
391
392        let mut tag = String::with_capacity(self.original_handle.len() + self.suffix.len());
393        tag.push_str(&self.original_handle);
394        tag.push_str(&self.suffix);
395        tag
396    }
397}
398
399impl Display for Tag {
400    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
401        if self.handle == "!" {
402            write!(f, "!{}", self.suffix)
403        } else {
404            write!(f, "{}{}", self.handle, self.suffix)
405        }
406    }
407}
408
409impl<'input> Event<'input> {
410    /// Return the anchor ID defined by this event, if any.
411    ///
412    /// Returns `Some(id)` when this event defines an anchor on a scalar, sequence, or mapping
413    /// node. Returns `None` for all other events, including `Alias` (which references an anchor
414    /// rather than defining one; use [`Self::alias_id`] to obtain the target anchor ID).
415    #[must_use]
416    pub fn anchor_id(&self) -> Option<usize> {
417        match self {
418            Self::Scalar(_, _, anchor_id, _)
419            | Self::SequenceStart(_, anchor_id, _)
420            | Self::MappingStart(_, anchor_id, _)
421                if *anchor_id != 0 =>
422            {
423                Some(*anchor_id)
424            }
425            _ => None,
426        }
427    }
428
429    /// Return the target anchor ID referenced by this alias event, if this event is an alias.
430    #[must_use]
431    pub fn alias_id(&self) -> Option<usize> {
432        match self {
433            Self::Alias(anchor_id) => Some(*anchor_id),
434            _ => None,
435        }
436    }
437
438    /// Return the resolved tag carried by this node event, if any.
439    #[must_use]
440    pub fn tag(&self) -> Option<&Tag> {
441        match self {
442            Self::Scalar(_, _, _, tag)
443            | Self::SequenceStart(_, _, tag)
444            | Self::MappingStart(_, _, tag) => tag.as_deref(),
445            _ => None,
446        }
447    }
448
449    /// Return the scalar value and style, if this event is a scalar.
450    #[must_use]
451    pub fn scalar(&self) -> Option<(&str, ScalarStyle)> {
452        match self {
453            Self::Scalar(value, style, _, _) => Some((value.as_ref(), *style)),
454            _ => None,
455        }
456    }
457
458    /// Return whether this event represents a YAML node (value).
459    ///
460    /// Returns `true` for scalars, collection starts, and aliases — all events that produce a
461    /// value in the document tree. Returns `false` for structural events such as `StreamStart`,
462    /// `DocumentStart`, collection ends, etc.
463    #[must_use]
464    pub fn is_node(&self) -> bool {
465        matches!(
466            self,
467            Self::Alias(_) | Self::Scalar(..) | Self::SequenceStart(..) | Self::MappingStart(..)
468        )
469    }
470
471    /// Create an empty scalar.
472    fn empty_scalar() -> Self {
473        // a null scalar
474        Event::Scalar("~".into(), ScalarStyle::Plain, 0, None)
475    }
476
477    /// Create an empty scalar with the given node properties.
478    fn empty_scalar_with_anchor(anchor: usize, tag: Option<Cow<'input, Tag>>) -> Self {
479        let value = if tag.is_some() {
480            Cow::default()
481        } else {
482            "~".into()
483        };
484
485        Event::Scalar(value, ScalarStyle::Plain, anchor, tag)
486    }
487}
488
489/// A YAML parser.
490#[derive(Debug)]
491pub struct Parser<'input, T: BorrowedInput<'input>> {
492    /// The underlying scanner from which we pull tokens.
493    scanner: Scanner<'input, T>,
494    /// Maximum number of comments retained while resolving an ambiguous collection entry.
495    max_buffered_comment_events: usize,
496    /// The stack of _previous_ states we were in.
497    ///
498    /// States are pushed in the context of subobjects to this stack. The top-most element is the
499    /// state in which to come back to when exiting the current state.
500    states: Vec<State>,
501    /// The state in which we currently are.
502    state: State,
503    /// The next token from the scanner.
504    token: Option<QueuedToken<'input>>,
505    /// The next YAML event to emit.
506    current: Option<(Event<'input>, Span)>,
507    /// The next parser error to emit after it has been observed by `peek`.
508    current_error: Option<ScanError>,
509    /// A scanner error discovered while ordering events that must be emitted first.
510    ///
511    /// Unlike `current_error`, this has not been exposed through `peek`. It is consumed by
512    /// `next_event_impl` after already-buffered events so `peek`, iteration, and `load` all retain
513    /// the same ordering.
514    deferred_error: Option<ScanError>,
515    /// YAML events buffered by parser states that need to emit an earlier synthetic node first.
516    queued_events: VecDeque<(Event<'input>, Span)>,
517
518    /// Pending indentation hint to be attached to the next emitted event span.
519    ///
520    /// This is used to communicate indentation for block mapping keys. It is set when consuming a
521    /// `TokenType::Key` in block style, and is applied to the next emitted node event (the key
522    /// itself).
523    pending_key_indent: Option<usize>,
524    /// Pending anchor ID to attach to a node after an intervening comment.
525    pending_node_anchor_id: usize,
526    /// Pending tag to attach to a node after an intervening comment.
527    pending_node_tag: Option<Cow<'input, Tag>>,
528    /// Pending explicit tag token start to attach to a node after an intervening comment.
529    pending_node_tag_start: Option<Marker>,
530    /// Pending end marker of the last node-property token before an intervening comment.
531    pending_node_property_end: Option<Marker>,
532    /// Pending empty scalar span captured before an intervening comment.
533    pending_empty_scalar_span: Option<Span>,
534    /// End marker of the most recently produced non-comment event.
535    ///
536    /// Synthetic syntax events use this marker, so presentation-only comments must not affect it.
537    last_non_comment_event_end: Option<Marker>,
538    /// Pending YAML version captured before comments preceding an explicit document start.
539    pending_document_version: Option<YamlVersion>,
540    /// Whether document directives were already initialized before comments preceding `---`.
541    pending_document_directives: bool,
542    /// `%TAG` handles already seen before comments preceding an explicit document start.
543    pending_document_tag_handles: BTreeSet<Cow<'input, str>>,
544    /// Anchors that have been encountered in the YAML document.
545    anchors: BTreeMap<Cow<'input, str>, usize>,
546    /// Next ID available for an anchor.
547    ///
548    /// Every anchor is given a unique ID. We use an incrementing ID and this is both the ID to
549    /// return for the next anchor and the count of anchor IDs emitted.
550    anchor_id_count: usize,
551    /// The tag directives (`%TAG`) the parser has encountered.
552    ///
553    /// Key is the handle, and value is the prefix.
554    tags: BTreeMap<Cow<'input, str>, Cow<'input, str>>,
555    /// Whether we have emitted a terminal iterator result.
556    ///
557    /// Terminal means either [`Event::StreamEnd`] or a [`ScanError`]. Emitted means that it has
558    /// been returned from [`Self::next_event`] or [`Self::next`]. If the terminal result is stored
559    /// in [`Self::current`], [`Self::current_error`], or [`Self::deferred_error`], this is set to
560    /// `false`.
561    stream_end_emitted: bool,
562    /// Make tags global across all documents.
563    keep_tags: bool,
564}
565
566/// Trait to be implemented in order to use the low-level parsing API.
567///
568/// The low-level parsing API is event-based (a push parser), calling [`EventReceiver::on_event`]
569/// for each YAML [`Event`] that occurs.
570/// The [`EventReceiver`] trait only receives events. In order to receive both events and their
571/// location in the source, use [`SpannedEventReceiver`]. Note that [`EventReceiver`]s implement
572/// [`SpannedEventReceiver`] automatically.
573/// Non-spanned receivers receive [`Event::Comment(text, placement)`](Event::Comment) like any
574/// other event, but without source location. Spanned receivers receive the same comment event plus
575/// the comment [`Span`] in [`SpannedEventReceiver::on_event`]. For comments, that span covers the
576/// whole source comment, including `#` and excluding the line break. When parsing from an input
577/// with byte offsets, such as [`Parser::new_from_str`], [`Span::slice`] returns that source
578/// comment text.
579///
580/// # Event hierarchy
581/// The event stream starts with an [`Event::StreamStart`] event followed by an
582/// [`Event::DocumentStart`] event. If the YAML document starts with a mapping (an object), an
583/// [`Event::MappingStart`] event is emitted. If it starts with a sequence (an array), an
584/// [`Event::SequenceStart`] event is emitted. Otherwise, an [`Event::Scalar`] event is emitted.
585///
586/// In a mapping, key-values are sent as consecutive data events. Comments can appear in the raw
587/// event stream between a key and its value; they are presentation metadata, not YAML data nodes.
588/// Consumers building YAML data trees should ignore [`Event::Comment`]. Any key/value alternation
589/// shortcut applies only after filtering out comments and other presentation metadata. After that
590/// filtering, the first event after an [`Event::MappingStart`] will be the key, and the following
591/// event will be its value. If the mapping contains no sub-mapping or sub-sequence, then even events
592/// (starting from 0) will always be keys and odd ones will always be values. The mapping ends when
593/// an [`Event::MappingEnd`] event is received.
594///
595/// In a sequence, values are sent consecutively until the [`Event::SequenceEnd`] event.
596///
597/// If a value is a sub-mapping or a sub-sequence, an [`Event::MappingStart`] or
598/// [`Event::SequenceStart`] event will be sent respectively. Following events until the associated
599/// [`Event::MappingEnd`] or [`Event::SequenceEnd`] (beware of nested mappings or sequences) will
600/// be part of the value and not another key-value pair or element in the sequence.
601///
602/// For instance, the following YAML:
603/// ```yaml
604/// a: b
605/// c:
606///   d: e
607/// f:
608///   - g
609///   - h
610/// ```
611/// will emit (indented and commented for visibility):
612/// ```text
613/// StreamStart, DocumentStart, MappingStart,
614///   Scalar("a", ..), Scalar("b", ..)
615///   Scalar("c", ..), MappingStart, Scalar("d", ..), Scalar("e", ..), MappingEnd,
616///   Scalar("f", ..), SequenceStart, Scalar("g", ..), Scalar("h", ..), SequenceEnd,
617/// MappingEnd, DocumentEnd, StreamEnd
618/// ```
619///
620/// # Example
621/// ```
622/// # use granit_parser::{Event, EventReceiver, Parser};
623/// #
624/// /// Sink of events. Collects them into an array.
625/// struct EventSink<'input> {
626///     events: Vec<Event<'input>>,
627/// }
628///
629/// /// Implement `on_event`, pushing into `self.events`.
630/// impl<'input> EventReceiver<'input> for EventSink<'input> {
631///     fn on_event(&mut self, ev: Event<'input>) {
632///         self.events.push(ev);
633///     }
634/// }
635///
636/// /// Load events from a YAML string.
637/// fn str_to_events(yaml: &str) -> Vec<Event<'_>> {
638///     let mut sink = EventSink { events: Vec::new() };
639///     let mut parser = Parser::new_from_str(yaml);
640///     // Load events using our sink as the receiver.
641///     parser.load(&mut sink, true).unwrap();
642///     sink.events
643/// }
644/// ```
645pub trait EventReceiver<'input> {
646    /// Handler called for each YAML event that is emitted by the parser.
647    fn on_event(&mut self, ev: Event<'input>);
648}
649
650/// Trait to be implemented for using the low-level parsing API.
651///
652/// Functionally similar to [`EventReceiver`], but receives a [`Span`] as well as the event.
653/// For [`Event::Comment`], the span is the source range of the whole comment.
654pub trait SpannedEventReceiver<'input> {
655    /// Handler called for each event that occurs.
656    fn on_event(&mut self, ev: Event<'input>, span: Span);
657}
658
659impl<'input, R: EventReceiver<'input>> SpannedEventReceiver<'input> for R {
660    fn on_event(&mut self, ev: Event<'input>, _span: Span) {
661        self.on_event(ev);
662    }
663}
664
665/// Trait to be implemented for fallible event handling without source spans.
666///
667/// This is the fallible counterpart to [`EventReceiver`]. Use it with [`Parser::try_load`] when
668/// event handling may need to stop parsing by returning an application error.
669pub trait TryEventReceiver<'input> {
670    /// Error returned by this receiver.
671    type Error;
672
673    /// Handler called for each YAML event that is emitted by the parser.
674    ///
675    /// Returning an error stops [`Parser::try_load`] immediately.
676    ///
677    /// # Errors
678    /// Returns `Self::Error` when the receiver wants to stop parsing.
679    fn on_event(&mut self, ev: Event<'input>) -> Result<(), Self::Error>;
680}
681
682/// Trait to be implemented for fallible event handling with source spans.
683///
684/// This is the fallible counterpart to [`SpannedEventReceiver`]. Use it with
685/// [`Parser::try_load`] when event handling may need to stop parsing by returning an application
686/// error.
687pub trait TrySpannedEventReceiver<'input> {
688    /// Error returned by this receiver.
689    type Error;
690
691    /// Handler called for each event that occurs.
692    ///
693    /// Returning an error stops [`Parser::try_load`] immediately.
694    ///
695    /// # Errors
696    /// Returns `Self::Error` when the receiver wants to stop parsing.
697    fn on_event(&mut self, ev: Event<'input>, span: Span) -> Result<(), Self::Error>;
698}
699
700impl<'input, R: TryEventReceiver<'input>> TrySpannedEventReceiver<'input> for R {
701    type Error = R::Error;
702
703    fn on_event(&mut self, ev: Event<'input>, _span: Span) -> Result<(), Self::Error> {
704        TryEventReceiver::on_event(self, ev)
705    }
706}
707
708/// Error returned by [`Parser::try_load`] and [`ParserTrait::try_load`].
709#[derive(Clone, PartialEq, Debug, Eq)]
710pub enum TryLoadError<E> {
711    /// Scanning or parsing failed.
712    Scan(
713        /// The scanner or parser error.
714        ScanError,
715    ),
716    /// The receiver returned an application error.
717    Receiver(
718        /// The error returned by the receiver.
719        E,
720    ),
721}
722
723impl<E> TryLoadError<E> {
724    #[cold]
725    fn scan(error: ScanError) -> Self {
726        Self::Scan(error)
727    }
728
729    #[cold]
730    fn receiver(error: E) -> Self {
731        Self::Receiver(error)
732    }
733}
734
735impl<E> From<ScanError> for TryLoadError<E> {
736    #[cold]
737    fn from(error: ScanError) -> Self {
738        Self::scan(error)
739    }
740}
741
742impl<E: Display> Display for TryLoadError<E> {
743    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
744        match self {
745            Self::Scan(error) => write!(f, "parser error: {error}"),
746            Self::Receiver(error) => write!(f, "receiver error: {error}"),
747        }
748    }
749}
750
751impl<E> core::error::Error for TryLoadError<E>
752where
753    E: core::error::Error + 'static,
754{
755    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
756        match self {
757            Self::Scan(error) => Some(error),
758            Self::Receiver(error) => Some(error),
759        }
760    }
761}
762
763fn try_emit<'input, R>(
764    recv: &mut R,
765    ev: Event<'input>,
766    span: Span,
767) -> Result<(), TryLoadError<R::Error>>
768where
769    R: TrySpannedEventReceiver<'input>,
770{
771    recv.on_event(ev, span).map_err(TryLoadError::receiver)
772}
773
774struct InfallibleSpannedReceiver<'receiver, R>(&'receiver mut R);
775
776impl<'input, R: SpannedEventReceiver<'input>> TrySpannedEventReceiver<'input>
777    for InfallibleSpannedReceiver<'_, R>
778{
779    type Error = Infallible;
780
781    fn on_event(&mut self, ev: Event<'input>, span: Span) -> Result<(), Self::Error> {
782        self.0.on_event(ev, span);
783        Ok(())
784    }
785}
786
787fn into_scan_result(result: Result<(), TryLoadError<Infallible>>) -> Result<(), ScanError> {
788    match result {
789        Ok(()) => Ok(()),
790        Err(TryLoadError::Scan(error)) => error.into_result(),
791        Err(TryLoadError::Receiver(error)) => match error {},
792    }
793}
794
795/// A convenience alias for a parser event result.
796pub type ParseResult<'input> = Result<(Event<'input>, Span), ScanError>;
797
798/// Trait extracted from `Parser` to support mocking and alternative implementations.
799pub trait ParserTrait<'input> {
800    /// Try to load the next event and return it without consuming it from `self`.
801    fn peek(&mut self) -> Option<Result<&(Event<'input>, Span), ScanError>>;
802
803    /// Try to load the next event and return it, consuming it from `self`.
804    fn next_event(&mut self) -> Option<ParseResult<'input>>;
805
806    /// Load the YAML from the stream in `self`, pushing events into `recv`.
807    ///
808    /// Use this method when event handling is infallible. If receiver code can return an
809    /// application error and should stop parsing, use [`ParserTrait::try_load`] instead. If the
810    /// caller should directly control when the next event is read, use [`ParserTrait::next_event`]
811    /// or [`Parser`]'s [`core::iter::Iterator`] implementation.
812    ///
813    /// # Errors
814    /// Returns `ScanError` when scanning or parsing the stream fails.
815    fn load<R: SpannedEventReceiver<'input>>(
816        &mut self,
817        recv: &mut R,
818        multi: bool,
819    ) -> Result<(), ScanError>;
820
821    /// Load the YAML from the stream in `self`, stopping if `recv` returns an error.
822    ///
823    /// If `multi` is set to `true`, the parser will allow parsing of multiple YAML documents
824    /// inside the stream.
825    ///
826    /// If the receiver returns an error, the parser is left positioned immediately after the event
827    /// that caused the receiver error. Callers should treat the parser as partially consumed.
828    ///
829    /// # Errors
830    /// Returns [`TryLoadError::Scan`] when scanning or parsing the stream fails. Returns
831    /// [`TryLoadError::Receiver`] when `recv` returns an error.
832    fn try_load<R: TrySpannedEventReceiver<'input>>(
833        &mut self,
834        recv: &mut R,
835        multi: bool,
836    ) -> Result<(), TryLoadError<R::Error>> {
837        while let Some(res) = self.next_event() {
838            let (ev, span) = res?;
839            let is_doc_end = matches!(ev, Event::DocumentEnd);
840            let is_stream_end = matches!(ev, Event::StreamEnd);
841
842            try_emit(recv, ev, span)?;
843
844            if is_stream_end {
845                break;
846            }
847            if !multi && is_doc_end {
848                break;
849            }
850        }
851
852        Ok(())
853    }
854}
855
856impl<'input> Parser<'input, StrInput<'input>> {
857    /// Create a parser over a borrowed string slice.
858    #[must_use]
859    pub fn new_from_str(value: &'input str) -> Self {
860        Self::new_from_str_with_options(value, Options::default())
861    }
862
863    /// Create a parser over a borrowed string slice with configurable behavior and resource
864    /// limits.
865    #[must_use]
866    pub fn new_from_str_with_options(value: &'input str, options: Options) -> Self {
867        Parser::with_options(StrInput::new(value), options)
868    }
869}
870
871impl<T> Parser<'static, BufferedInput<T>>
872where
873    T: Iterator<Item = char>,
874{
875    /// Create a parser over an iterator of characters.
876    #[must_use]
877    pub fn new_from_iter(iter: T) -> Self {
878        Self::new_from_iter_with_options(iter, Options::default())
879    }
880
881    /// Create a parser over an iterator of characters with configurable behavior and resource
882    /// limits.
883    #[must_use]
884    pub fn new_from_iter_with_options(iter: T, options: Options) -> Self {
885        Parser::with_options(BufferedInput::new(iter), options)
886    }
887}
888
889impl<T> Parser<'static, FallibleBufferedInput<T>>
890where
891    T: Iterator<Item = Result<char, ErrorKind>>,
892{
893    /// Create a parser over a fallible iterator of characters.
894    ///
895    /// The iterator's `None` return value means clean end-of-input. An `Err` item reports a
896    /// terminal source failure and is returned by the parser as a [`ScanError`] carrying the same
897    /// [`ErrorKind`]. The iterator is not polled again after its first error.
898    #[must_use]
899    pub fn new_from_fallible_iter(iter: T) -> Self {
900        Self::new_from_fallible_iter_with_options(iter, Options::default())
901    }
902
903    /// Create a parser over a fallible iterator of characters with configurable behavior and
904    /// resource limits.
905    ///
906    /// The iterator's `None` return value means clean end-of-input. An `Err` item reports a
907    /// terminal source failure and is returned by the parser as a [`ScanError`] carrying the same
908    /// [`ErrorKind`]. The iterator is not polled again after its first error.
909    #[must_use]
910    pub fn new_from_fallible_iter_with_options(iter: T, options: Options) -> Self {
911        Parser::with_options(FallibleBufferedInput::new(iter), options)
912    }
913}
914
915impl<'input, T: BorrowedInput<'input>> Parser<'input, T> {
916    /// Return the next anchor ID that will be assigned by this parser.
917    #[must_use]
918    pub fn anchor_offset(&self) -> usize {
919        self.anchor_id_count
920    }
921
922    /// Set the next anchor ID that will be assigned by this parser.
923    pub fn set_anchor_offset(&mut self, offset: usize) {
924        self.anchor_id_count = offset;
925    }
926
927    /// Create a parser over a custom input source.
928    #[must_use]
929    pub fn new(src: T) -> Self {
930        Self::with_options(src, Options::default())
931    }
932
933    /// Create a parser over a custom input source with configurable behavior and resource limits.
934    ///
935    /// Use [`crate::options!`] to construct `options` without depending on exhaustive struct
936    /// literal syntax.
937    #[must_use]
938    pub fn with_options(src: T, options: Options) -> Self {
939        let max_buffered_comment_events = options.max_buffered_comment_events;
940
941        Parser {
942            scanner: Scanner::with_options(src, options),
943            max_buffered_comment_events,
944            states: Vec::new(),
945            state: State::StreamStart,
946            token: None,
947            current: None,
948            current_error: None,
949            deferred_error: None,
950            queued_events: VecDeque::new(),
951
952            pending_key_indent: None,
953            pending_node_anchor_id: 0,
954            pending_node_tag: None,
955            pending_node_tag_start: None,
956            pending_node_property_end: None,
957            pending_empty_scalar_span: None,
958            last_non_comment_event_end: None,
959            pending_document_version: None,
960            pending_document_directives: false,
961            pending_document_tag_handles: BTreeSet::new(),
962
963            anchors: BTreeMap::new(),
964            // valid anchor_id starts from 1
965            anchor_id_count: 1,
966            tags: BTreeMap::new(),
967            stream_end_emitted: false,
968            keep_tags: false,
969        }
970    }
971
972    /// Configure whether tag directives remain active across document boundaries.
973    ///
974    /// This behavior is non-standard as per the YAML specification but can be encountered in the
975    /// wild. Passing `true` enables this non-standard extension and allows the parser to accept
976    /// input from [test
977    /// QLJ7](https://github.com/yaml/yaml-test-suite/blob/ccfa74e56afb53da960847ff6e6976c0a0825709/src/QLJ7.yaml)
978    /// of the yaml-test-suite:
979    ///
980    /// ```yaml
981    /// %TAG !prefix! tag:example.com,2011:
982    /// --- !prefix!A
983    /// a: b
984    /// --- !prefix!B
985    /// c: d
986    /// --- !prefix!C
987    /// e: f
988    /// ```
989    ///
990    /// With `keep_tags` set to `false`, the above YAML is rejected. As per the specification, tags
991    /// only apply to the document immediately following them. This would error on `!prefix!B`.
992    ///
993    /// With `keep_tags` set to `true`, the above YAML is accepted by the parser.
994    #[must_use]
995    pub fn keep_tags(mut self, value: bool) -> Self {
996        self.keep_tags = value;
997        self
998    }
999
1000    /// Try to load the next event and return it without consuming it from `self`.
1001    ///
1002    /// Any subsequent call to [`Parser::peek`] will return the same value, until a call to
1003    /// [`Iterator::next`] or [`Parser::load`].
1004    /// If the buffered value is a [`ScanError`], [`Parser::next_event`] returns that error once
1005    /// and then the parser is exhausted.
1006    ///
1007    /// # Errors
1008    /// Returns `ScanError` when loading the next event fails.
1009    pub fn peek(&mut self) -> Option<Result<&(Event<'input>, Span), ScanError>> {
1010        ParserTrait::peek(self)
1011    }
1012
1013    /// Try to load the next event and return it, consuming it from `self`.
1014    ///
1015    /// After this returns a [`ScanError`], subsequent calls return [`None`].
1016    ///
1017    /// # Errors
1018    /// Returns `ScanError` when loading the next event fails.
1019    pub fn next_event(&mut self) -> Option<ParseResult<'input>> {
1020        ParserTrait::next_event(self)
1021    }
1022
1023    /// Implementation function for [`Self::next_event`] without the `Option`.
1024    ///
1025    /// [`Self::next_event`] should conform to the expectations of an [`Iterator`] and return an
1026    /// option. This burdens the parser code. This function is used internally when an option is
1027    /// undesirable.
1028    fn next_event_impl<'a>(&mut self) -> ParseResult<'a>
1029    where
1030        'input: 'a,
1031    {
1032        let event = match self.current.take() {
1033            None => {
1034                if let Some(event) = self.queued_events.pop_front() {
1035                    Ok(self.apply_pending_key_indent(event))
1036                } else if let Some(error) = self.deferred_error.take() {
1037                    return Err(error);
1038                } else if self.state == State::End {
1039                    self.parse()
1040                } else if let Some(comment) = self.maybe_next_comment_event()? {
1041                    Ok(comment)
1042                } else {
1043                    self.parse()
1044                }
1045            }
1046            Some(v) => Ok(v),
1047        }?;
1048
1049        Ok(self.remember_non_comment_event_end(event))
1050    }
1051
1052    fn apply_pending_key_indent<'a>(&mut self, (ev, span): (Event<'a>, Span)) -> (Event<'a>, Span) {
1053        if ev.is_node() {
1054            if let Some(indent) = self.pending_key_indent.take() {
1055                return (ev, span.with_indent(Some(indent)));
1056            }
1057        }
1058
1059        (ev, span)
1060    }
1061
1062    fn remember_non_comment_event_end<'a>(
1063        &mut self,
1064        (event, span): (Event<'a>, Span),
1065    ) -> (Event<'a>, Span) {
1066        if !matches!(event, Event::Comment(..)) {
1067            self.last_non_comment_event_end = Some(span.end);
1068        }
1069        (event, span)
1070    }
1071
1072    /// Peek at the next token from the scanner.
1073    fn peek_token(&mut self) -> Result<&QueuedToken<'_>, ScanError> {
1074        if let Some(error) = &self.deferred_error {
1075            return Err(error.clone());
1076        }
1077
1078        match self.token {
1079            None => {
1080                self.token = Some(self.scan_next_token()?);
1081                Ok(self.token.as_ref().unwrap())
1082            }
1083            Some(ref tok) => Ok(tok),
1084        }
1085    }
1086
1087    /// Extract and return the next token from the scanner.
1088    ///
1089    /// This function does _not_ make use of `self.token`.
1090    fn scan_next_token(&mut self) -> Result<QueuedToken<'input>, ScanError> {
1091        match self.scanner.next_queued_token()? {
1092            None => unreachable!("scanner ended before the parser consumed its stream-end token"),
1093            Some(tok) => Ok(tok),
1094        }
1095    }
1096
1097    #[inline]
1098    fn maybe_next_comment_event<'a>(&mut self) -> Result<Option<(Event<'a>, Span)>, ScanError>
1099    where
1100        'input: 'a,
1101    {
1102        if self.scanner.comments_possible() {
1103            self.next_comment_event()
1104        } else {
1105            Ok(None)
1106        }
1107    }
1108
1109    fn next_comment_event<'a>(&mut self) -> Result<Option<(Event<'a>, Span)>, ScanError>
1110    where
1111        'input: 'a,
1112    {
1113        let is_comment = {
1114            let token = self.peek_token()?;
1115            matches!(token.1, QueuedTokenType::Comment(_))
1116        };
1117
1118        if !is_comment {
1119            return Ok(None);
1120        }
1121
1122        let QueuedToken(span, token) = self.fetch_token();
1123        match token {
1124            QueuedTokenType::Comment(comment) => {
1125                let placement = self.refined_comment_placement(span, comment.placement());
1126                Ok(Some((Event::Comment(comment.into_text(), placement), span)))
1127            }
1128            _ => unreachable!("comment token disappeared after peek"),
1129        }
1130    }
1131
1132    #[inline]
1133    fn next_comment_events(&mut self) -> Result<Vec<(Event<'input>, Span)>, ScanError> {
1134        if !self.scanner.comments_possible() {
1135            return Ok(Vec::new());
1136        }
1137
1138        let mut events = Vec::new();
1139        loop {
1140            match self.peek_token() {
1141                Ok(token) if matches!(token.1, QueuedTokenType::Comment(_)) => {}
1142                Err(error) if events.is_empty() => return Err(error),
1143                Err(error) => {
1144                    debug_assert!(self.deferred_error.is_none());
1145                    self.deferred_error = Some(error);
1146                    return Ok(events);
1147                }
1148                Ok(_) => return Ok(events),
1149            }
1150
1151            if events.len() >= self.max_buffered_comment_events {
1152                return Err(ScanError::from_kind(
1153                    self.peek_token()?.0.start,
1154                    ErrorKind::TooManyComments,
1155                ));
1156            }
1157
1158            let comment = self
1159                .next_comment_event()?
1160                .expect("comment token disappeared after peek");
1161            events.push(comment);
1162            if self.deferred_error.is_some() {
1163                return Ok(events);
1164            }
1165        }
1166    }
1167
1168    fn queue_tail_and_return_first(
1169        &mut self,
1170        events: Vec<(Event<'input>, Span)>,
1171    ) -> (Event<'input>, Span) {
1172        let mut events = events.into_iter();
1173        let first = events
1174            .next()
1175            .expect("event queue must contain at least one event");
1176        self.queued_events.extend(events);
1177        first
1178    }
1179
1180    fn queue_event_by_span(
1181        &mut self,
1182        comments: Vec<(Event<'input>, Span)>,
1183        event: (Event<'input>, Span),
1184    ) -> (Event<'input>, Span) {
1185        let insert_at = comments
1186            .iter()
1187            .position(|(_, comment_span)| {
1188                comment_span.start.index() >= event.1.start.index()
1189                    && comment_span.end.index() >= event.1.end.index()
1190            })
1191            .unwrap_or(comments.len());
1192        let mut ordered = Vec::with_capacity(comments.len() + 1);
1193        let mut comments = comments.into_iter();
1194
1195        for _ in 0..insert_at {
1196            ordered.push(
1197                comments
1198                    .next()
1199                    .expect("comment disappeared while ordering queued events"),
1200            );
1201        }
1202        ordered.push(event);
1203        ordered.extend(comments);
1204
1205        self.queue_tail_and_return_first(ordered)
1206    }
1207
1208    fn queue_two_events_by_span(
1209        &mut self,
1210        comments: Vec<(Event<'input>, Span)>,
1211        first: (Event<'input>, Span),
1212        second: (Event<'input>, Span),
1213    ) -> (Event<'input>, Span) {
1214        let insert_at = comments
1215            .iter()
1216            .position(|(_, comment_span)| {
1217                comment_span.start.index() >= first.1.start.index()
1218                    && comment_span.end.index() >= first.1.end.index()
1219            })
1220            .unwrap_or(comments.len());
1221        let mut ordered = Vec::with_capacity(comments.len() + 2);
1222        let mut comments = comments.into_iter();
1223
1224        for _ in 0..insert_at {
1225            ordered.push(
1226                comments
1227                    .next()
1228                    .expect("comment disappeared while ordering queued events"),
1229            );
1230        }
1231        ordered.push(first);
1232        ordered.push(second);
1233        ordered.extend(comments);
1234
1235        self.queue_tail_and_return_first(ordered)
1236    }
1237
1238    fn refined_comment_placement(&mut self, span: Span, placement: Placement) -> Placement {
1239        if placement == Placement::Right {
1240            return Placement::Right;
1241        }
1242
1243        let next = match self.peek_token() {
1244            Ok(next) => next,
1245            Err(error) => {
1246                debug_assert!(self.deferred_error.is_none());
1247                self.deferred_error = Some(error);
1248                return placement;
1249            }
1250        };
1251        if matches!(next.1, QueuedTokenType::StreamEnd) {
1252            return Placement::Last;
1253        }
1254
1255        if next.0.start.line() == span.end.line() + 1 {
1256            Placement::Above
1257        } else {
1258            Placement::Free
1259        }
1260    }
1261
1262    /// Take the token buffered by [`Self::peek_token`].
1263    ///
1264    /// # Panics
1265    /// Panics if no token has been buffered.
1266    #[track_caller]
1267    fn fetch_token<'a>(&mut self) -> QueuedToken<'a>
1268    where
1269        'input: 'a,
1270    {
1271        self.token
1272            .take()
1273            .expect("fetch_token needs to be preceded by peek_token")
1274    }
1275
1276    /// Skip the next token from the scanner.
1277    fn skip(&mut self) {
1278        self.token = None;
1279    }
1280    /// Pops the top-most state and make it the current state.
1281    ///
1282    /// # Panics
1283    /// Panics if the state stack is empty.
1284    #[track_caller]
1285    fn pop_state(&mut self) {
1286        self.state = self.states.pop().unwrap();
1287    }
1288    /// Push a new state atop the state stack.
1289    fn push_state(&mut self, state: State) {
1290        self.states.push(state);
1291    }
1292
1293    fn defer_parse_node<'a>(
1294        &mut self,
1295        node_state: State,
1296        return_state: State,
1297        block: bool,
1298        indentless_sequence: bool,
1299    ) -> ParseResult<'a>
1300    where
1301        'input: 'a,
1302    {
1303        self.push_state(return_state);
1304        self.state = node_state;
1305        if let Some(comment) = self.maybe_next_comment_event()? {
1306            Ok(comment)
1307        } else {
1308            self.parse_node(block, indentless_sequence)
1309        }
1310    }
1311
1312    fn parse<'a>(&mut self) -> ParseResult<'a>
1313    where
1314        'input: 'a,
1315    {
1316        if self.state == State::End {
1317            return Ok((Event::StreamEnd, Span::empty(self.scanner.mark())));
1318        }
1319        let event = self.state_machine()?;
1320        Ok(self.apply_pending_key_indent(event))
1321    }
1322
1323    /// Load the YAML from the stream in `self`, pushing events into `recv`.
1324    ///
1325    /// The contents of the stream are parsed and the corresponding events are sent into the
1326    /// receiver. For detailed explanations about how events work, see [`EventReceiver`].
1327    ///
1328    /// If `multi` is set to `true`, the parser will allow parsing of multiple YAML documents
1329    /// inside the stream.
1330    ///
1331    /// Use this method when event handling is infallible. If receiver code can return an
1332    /// application error and should stop parsing, use [`Parser::try_load`] instead. If the caller
1333    /// should directly control when the next event is read, use [`Parser`]'s
1334    /// [`core::iter::Iterator`] implementation.
1335    ///
1336    /// Note that any [`EventReceiver`] is also a [`SpannedEventReceiver`], so implementing the
1337    /// former is enough to call this function.
1338    ///
1339    /// # Example
1340    /// ```
1341    /// # use granit_parser::{Event, EventReceiver, Parser};
1342    /// # fn main() -> Result<(), granit_parser::ScanError> {
1343    /// struct EventSink<'input> {
1344    ///     events: Vec<Event<'input>>,
1345    /// }
1346    ///
1347    /// impl<'input> EventReceiver<'input> for EventSink<'input> {
1348    ///     fn on_event(&mut self, ev: Event<'input>) {
1349    ///         self.events.push(ev);
1350    ///     }
1351    /// }
1352    ///
1353    /// let mut parser = Parser::new_from_str("a: 1\n");
1354    /// let mut sink = EventSink { events: Vec::new() };
1355    ///
1356    /// parser.load(&mut sink, false)?;
1357    ///
1358    /// assert!(sink
1359    ///     .events
1360    ///     .iter()
1361    ///     .any(|ev| matches!(ev, Event::Scalar(value, ..) if value == "a")));
1362    /// # Ok(())
1363    /// # }
1364    /// ```
1365    ///
1366    /// # Errors
1367    /// Returns `ScanError` when loading fails.
1368    pub fn load<R: SpannedEventReceiver<'input>>(
1369        &mut self,
1370        recv: &mut R,
1371        multi: bool,
1372    ) -> Result<(), ScanError> {
1373        ParserTrait::load(self, recv, multi)
1374    }
1375
1376    /// Load the YAML from the stream in `self`, pushing events into `recv`.
1377    ///
1378    /// This is the fallible counterpart to [`Parser::load`]. If `recv` returns an error, parsing
1379    /// stops immediately and that error is returned as [`TryLoadError::Receiver`].
1380    ///
1381    /// If `multi` is set to `true`, the parser will allow parsing of multiple YAML documents
1382    /// inside the stream.
1383    ///
1384    /// If the receiver returns an error, the parser is left positioned immediately after the event
1385    /// that caused the receiver error. Callers should treat the parser as partially consumed.
1386    ///
1387    /// # Example
1388    /// ```
1389    /// # use granit_parser::{Event, Parser, TryEventReceiver, TryLoadError};
1390    /// #[derive(Debug, PartialEq, Eq)]
1391    /// enum ValidationError {
1392    ///     ForbiddenScalar,
1393    /// }
1394    ///
1395    /// struct Validator;
1396    ///
1397    /// impl<'input> TryEventReceiver<'input> for Validator {
1398    ///     type Error = ValidationError;
1399    ///
1400    ///     fn on_event(&mut self, ev: Event<'input>) -> Result<(), Self::Error> {
1401    ///         if matches!(ev, Event::Scalar(value, ..) if value.as_ref() == "bad") {
1402    ///             Err(ValidationError::ForbiddenScalar)
1403    ///         } else {
1404    ///             Ok(())
1405    ///         }
1406    ///     }
1407    /// }
1408    ///
1409    /// let mut parser = Parser::new_from_str("value: bad\n");
1410    /// let mut validator = Validator;
1411    ///
1412    /// let err = parser.try_load(&mut validator, false).unwrap_err();
1413    ///
1414    /// assert_eq!(err, TryLoadError::Receiver(ValidationError::ForbiddenScalar));
1415    /// ```
1416    ///
1417    /// # Errors
1418    /// Returns [`TryLoadError::Scan`] when scanning or parsing the stream fails. Returns
1419    /// [`TryLoadError::Receiver`] when `recv` returns an error.
1420    pub fn try_load<R: TrySpannedEventReceiver<'input>>(
1421        &mut self,
1422        recv: &mut R,
1423        multi: bool,
1424    ) -> Result<(), TryLoadError<R::Error>> {
1425        ParserTrait::try_load(self, recv, multi)
1426    }
1427
1428    fn state_machine<'a>(&mut self) -> ParseResult<'a>
1429    where
1430        'input: 'a,
1431    {
1432        debug_print!("\n\x1B[;33mParser state: {:?} \x1B[;0m", self.state);
1433
1434        match self.state {
1435            State::StreamStart => self.stream_start(),
1436
1437            State::ImplicitDocumentStart => self.document_start(true),
1438            State::DocumentStart => self.document_start(false),
1439            State::DocumentContent => self.document_content(),
1440            State::DocumentEnd => self.document_end(),
1441
1442            State::BlockNode => self.parse_node(true, false),
1443            State::BlockNodeOrIndentlessSequence => self.parse_node(true, true),
1444            State::FlowNode => self.parse_node(false, false),
1445            State::BlockMappingFirstKey => self.block_mapping_key(true),
1446            State::BlockMappingKey => self.block_mapping_key(false),
1447            State::BlockMappingKeyNode => self.block_mapping_key_node(),
1448            State::BlockMappingValue => self.block_mapping_value(),
1449            State::BlockMappingValueNode => self.block_mapping_value_node(),
1450
1451            State::BlockSequenceFirstEntry => self.block_sequence_entry(true),
1452            State::BlockSequenceEntry => self.block_sequence_entry(false),
1453            State::BlockSequenceEntryNode => self.block_sequence_entry_node(),
1454
1455            State::FlowSequenceFirstEntry => self.flow_sequence_entry(true),
1456            State::FlowSequenceEntry => self.flow_sequence_entry(false),
1457
1458            State::FlowMappingFirstKey => self.flow_mapping_key(true),
1459            State::FlowMappingKey => self.flow_mapping_key(false),
1460            State::FlowMappingKeyNode => self.flow_mapping_key_node(),
1461            State::FlowMappingValue => self.flow_mapping_value(false),
1462            State::FlowMappingValueNode => self.flow_mapping_value_node(),
1463
1464            State::IndentlessSequenceEntry => self.indentless_sequence_entry(),
1465            State::IndentlessSequenceEntryNode => self.indentless_sequence_entry_node(),
1466
1467            State::FlowSequenceEntryMappingKey => self.flow_sequence_entry_mapping_key(),
1468            State::FlowSequenceEntryMappingValue => self.flow_sequence_entry_mapping_value(),
1469            State::FlowSequenceEntryMappingValueNode => {
1470                self.flow_sequence_entry_mapping_value_node()
1471            }
1472            State::FlowSequenceEntryMappingEnd => self.flow_sequence_entry_mapping_end(),
1473            State::FlowMappingEmptyValue => self.flow_mapping_value(true),
1474
1475            State::End => unreachable!("end state is handled before state-machine dispatch"),
1476        }
1477    }
1478
1479    fn stream_start<'a>(&mut self) -> ParseResult<'a>
1480    where
1481        'input: 'a,
1482    {
1483        match *self.peek_token()? {
1484            QueuedToken(span, QueuedTokenType::StreamStart) => {
1485                self.state = State::ImplicitDocumentStart;
1486                self.skip();
1487                Ok((Event::StreamStart, span))
1488            }
1489            QueuedToken(span, _) => Err(ScanError::from_kind(
1490                span.start,
1491                ErrorKind::ExpectedStreamStart,
1492            )),
1493        }
1494    }
1495
1496    fn has_pending_document_directives(&self) -> bool {
1497        self.pending_document_directives
1498            || self.pending_document_version.is_some()
1499            || !self.pending_document_tag_handles.is_empty()
1500    }
1501
1502    fn document_start<'a>(&mut self, implicit: bool) -> ParseResult<'a>
1503    where
1504        'input: 'a,
1505    {
1506        // Resume a document start paused to emit comments before handling markers that are only
1507        // ignorable between documents. In particular, `...` is invalid while `---` is still
1508        // required after directives and must not be consumed by the loop below.
1509        if self.has_pending_document_directives() {
1510            return self.explicit_document_start();
1511        }
1512
1513        while let QueuedTokenType::DocumentEnd = self.peek_token()?.1 {
1514            self.skip();
1515        }
1516
1517        // Anchors are scoped to a single document.
1518        self.anchors.clear();
1519
1520        // Skipping a leading document-end marker can expose a comment that the normal
1521        // `next_event_impl` pre-dispatch check could not see yet. Emit it before deciding whether
1522        // another document starts; presentation-only comments must not create an implicit document.
1523        if let Some(comment) = self.maybe_next_comment_event()? {
1524            return Ok(comment);
1525        }
1526
1527        match *self.peek_token()? {
1528            QueuedToken(span, QueuedTokenType::StreamEnd) => {
1529                self.state = State::End;
1530                self.skip();
1531                Ok((Event::StreamEnd, span))
1532            }
1533            QueuedToken(
1534                _,
1535                QueuedTokenType::VersionDirective(..)
1536                | QueuedTokenType::TagDirective(..)
1537                | QueuedTokenType::ReservedDirective(..)
1538                | QueuedTokenType::DocumentStart,
1539            ) => {
1540                // explicit document
1541                self.explicit_document_start()
1542            }
1543            QueuedToken(span, _) if implicit => {
1544                self.parser_process_directives(None, false, BTreeSet::new())?;
1545                self.push_state(State::DocumentEnd);
1546                self.state = State::BlockNode;
1547                Ok((Event::DocumentStart(false, None), span))
1548            }
1549            _ => {
1550                // explicit document
1551                self.explicit_document_start()
1552            }
1553        }
1554    }
1555
1556    fn parser_process_directives(
1557        &mut self,
1558        mut version: Option<YamlVersion>,
1559        continuing: bool,
1560        mut document_tag_handles: BTreeSet<Cow<'input, str>>,
1561    ) -> Result<(Option<YamlVersion>, BTreeSet<Cow<'input, str>>), ScanError> {
1562        let mut tags = if continuing || self.keep_tags {
1563            core::mem::take(&mut self.tags)
1564        } else {
1565            BTreeMap::new()
1566        };
1567
1568        loop {
1569            let is_directive = matches!(
1570                self.peek_token()?.1,
1571                QueuedTokenType::VersionDirective(..)
1572                    | QueuedTokenType::TagDirective(..)
1573                    | QueuedTokenType::ReservedDirective(..)
1574            );
1575            if !is_directive {
1576                break;
1577            }
1578
1579            let QueuedToken(span, token) = self.fetch_token();
1580            match token {
1581                QueuedTokenType::VersionDirective(major, minor) => {
1582                    if version.is_some() {
1583                        return Err(ScanError::from_kind(
1584                            span.start,
1585                            ErrorKind::DuplicateVersionDirective,
1586                        ));
1587                    }
1588                    if major != 1 {
1589                        return Err(ScanError::from_kind(
1590                            span.start,
1591                            ErrorKind::UnsupportedYamlMajorVersion,
1592                        ));
1593                    }
1594                    version = Some(YamlVersion::new(major, minor));
1595                }
1596                QueuedTokenType::TagDirective(handle, prefix) => {
1597                    if !document_tag_handles.insert(handle.clone()) {
1598                        return Err(ScanError::from_kind(
1599                            span.start,
1600                            ErrorKind::DuplicateTagDirective,
1601                        ));
1602                    }
1603                    tags.insert(handle, prefix);
1604                }
1605                QueuedTokenType::ReservedDirective(_, _) => {
1606                    // Reserved directives are ignored
1607                }
1608                _ => unreachable!("non-directive token passed the directive guard"),
1609            }
1610        }
1611
1612        self.tags = tags;
1613        Ok((version, document_tag_handles))
1614    }
1615
1616    fn explicit_document_start<'a>(&mut self) -> ParseResult<'a>
1617    where
1618        'input: 'a,
1619    {
1620        let pending_version = self.pending_document_version.take();
1621        let continuing_directives = core::mem::take(&mut self.pending_document_directives);
1622        let pending_tag_handles = core::mem::take(&mut self.pending_document_tag_handles);
1623        let (version, document_tag_handles) = self.parser_process_directives(
1624            pending_version,
1625            continuing_directives,
1626            pending_tag_handles,
1627        )?;
1628        if let Some(comment) = self.maybe_next_comment_event()? {
1629            self.pending_document_version = version;
1630            self.pending_document_directives = true;
1631            self.pending_document_tag_handles = document_tag_handles;
1632            return Ok(comment);
1633        }
1634        match *self.peek_token()? {
1635            QueuedToken(mark, QueuedTokenType::DocumentStart) => {
1636                self.push_state(State::DocumentEnd);
1637                self.state = State::DocumentContent;
1638                self.skip();
1639                Ok((Event::DocumentStart(true, version), mark))
1640            }
1641            QueuedToken(span, _) => Err(ScanError::from_kind(
1642                span.start,
1643                ErrorKind::ExpectedDocumentStart,
1644            )),
1645        }
1646    }
1647
1648    fn document_content<'a>(&mut self) -> ParseResult<'a>
1649    where
1650        'input: 'a,
1651    {
1652        if let QueuedToken(
1653            mark,
1654            QueuedTokenType::VersionDirective(..)
1655            | QueuedTokenType::TagDirective(..)
1656            | QueuedTokenType::ReservedDirective(..)
1657            | QueuedTokenType::DocumentStart
1658            | QueuedTokenType::DocumentEnd
1659            | QueuedTokenType::StreamEnd,
1660        ) = *self.peek_token()?
1661        {
1662            self.pop_state();
1663            let span = self
1664                .last_non_comment_event_end
1665                .map_or_else(|| Span::empty(mark.start), Span::empty);
1666            Ok((Event::empty_scalar(), span))
1667        } else {
1668            self.state = State::BlockNode;
1669            self.parse_node(true, false)
1670        }
1671    }
1672
1673    fn document_end<'a>(&mut self) -> ParseResult<'a>
1674    where
1675        'input: 'a,
1676    {
1677        let mut explicit_end = false;
1678        let span: Span = match *self.peek_token()? {
1679            QueuedToken(span, QueuedTokenType::DocumentEnd) => {
1680                explicit_end = true;
1681                self.skip();
1682                span
1683            }
1684            QueuedToken(span, _) => self
1685                .last_non_comment_event_end
1686                .map_or_else(|| Span::empty(span.start), Span::empty),
1687        };
1688
1689        if self.keep_tags {
1690            // Never persist default handles across document boundaries. Allowing `%TAG !! ...`
1691            // or `%TAG ! ...` to leak into following documents lets earlier documents alter how
1692            // explicit tags are interpreted later on.
1693            self.tags.remove("!!");
1694            self.tags.remove("!");
1695        } else {
1696            self.tags.clear();
1697        }
1698        if explicit_end {
1699            self.state = State::ImplicitDocumentStart;
1700        } else {
1701            if let QueuedToken(
1702                span,
1703                QueuedTokenType::VersionDirective(..)
1704                | QueuedTokenType::TagDirective(..)
1705                | QueuedTokenType::ReservedDirective(..),
1706            ) = *self.peek_token()?
1707            {
1708                return Err(ScanError::from_kind(
1709                    span.start,
1710                    ErrorKind::MissingDocumentEndBeforeDirective,
1711                ));
1712            }
1713            self.state = State::DocumentStart;
1714        }
1715
1716        Ok((Event::DocumentEnd, span))
1717    }
1718
1719    fn register_anchor(&mut self, name: Cow<'input, str>, mark: &Span) -> Result<usize, ScanError> {
1720        // YAML permits anchor names to be reused. Aliases resolve to the most recent definition.
1721        let new_id = self.anchor_id_count;
1722        self.anchor_id_count = self
1723            .anchor_id_count
1724            .checked_add(1)
1725            .ok_or_else(|| ScanError::from_kind(mark.start, ErrorKind::AnchorCountOverflow))?;
1726        self.anchors.insert(name, new_id);
1727        Ok(new_id)
1728    }
1729
1730    fn save_pending_node_properties(
1731        &mut self,
1732        anchor_id: usize,
1733        tag: Option<Cow<'input, Tag>>,
1734        tag_start: Option<Marker>,
1735        property_end: Option<Marker>,
1736    ) {
1737        self.pending_node_anchor_id = anchor_id;
1738        self.pending_node_tag = tag;
1739        self.pending_node_tag_start = tag_start;
1740        self.pending_node_property_end = property_end;
1741    }
1742
1743    fn attach_tag_start(event: Event<'_>, span: Span, start: Option<Marker>) -> (Event<'_>, Span) {
1744        (event, span.with_tag_start(start))
1745    }
1746
1747    #[allow(clippy::too_many_lines)]
1748    fn parse_node<'a>(&mut self, block: bool, indentless_sequence: bool) -> ParseResult<'a>
1749    where
1750        'input: 'a,
1751    {
1752        if let Some(comment) = self.maybe_next_comment_event()? {
1753            return Ok(comment);
1754        }
1755
1756        let mut anchor_id = core::mem::take(&mut self.pending_node_anchor_id);
1757        let mut tag = self.pending_node_tag.take();
1758        let mut tag_start = self.pending_node_tag_start.take();
1759        let mut property_end = self.pending_node_property_end.take();
1760        match *self.peek_token()? {
1761            QueuedToken(_, QueuedTokenType::Alias(_)) if anchor_id == 0 && tag.is_none() => {
1762                self.pop_state();
1763                let QueuedToken(span, QueuedTokenType::Alias(name)) = self.fetch_token() else {
1764                    unreachable!("alias token disappeared after peek")
1765                };
1766                return match self.anchors.get(&*name) {
1767                    None => Err(ScanError::from_kind(span.start, ErrorKind::UnknownAnchor)),
1768                    Some(id) => Ok((Event::Alias(*id), span)),
1769                };
1770            }
1771            QueuedToken(_, QueuedTokenType::Anchor(_)) if anchor_id == 0 => {
1772                let QueuedToken(span, QueuedTokenType::Anchor(name)) = self.fetch_token() else {
1773                    unreachable!("anchor token disappeared after peek")
1774                };
1775                anchor_id = self.register_anchor(name, &span)?;
1776                property_end = Some(span.end);
1777                if tag.is_none() && matches!(self.peek_token()?.1, QueuedTokenType::Tag(..)) {
1778                    let QueuedToken(tag_span, QueuedTokenType::Tag(handle, suffix)) =
1779                        self.fetch_token()
1780                    else {
1781                        unreachable!("tag token disappeared after peek")
1782                    };
1783                    tag_start = Some(tag_span.start);
1784                    tag = Some(self.resolve_tag(tag_span, &handle, suffix)?);
1785                    property_end = Some(tag_span.end);
1786                }
1787                if let Some(comment) = self.maybe_next_comment_event()? {
1788                    self.save_pending_node_properties(anchor_id, tag, tag_start, property_end);
1789                    return Ok(comment);
1790                }
1791            }
1792            QueuedToken(mark, QueuedTokenType::Tag(..)) if tag.is_none() => {
1793                let QueuedTokenType::Tag(handle, suffix) = self.fetch_token().1 else {
1794                    unreachable!("tag token disappeared after peek")
1795                };
1796                tag_start = Some(mark.start);
1797                property_end = Some(mark.end);
1798                tag = Some(self.resolve_tag(mark, &handle, suffix)?);
1799                if anchor_id == 0 {
1800                    if let QueuedTokenType::Anchor(_) = &self.peek_token()?.1 {
1801                        let QueuedToken(mark, QueuedTokenType::Anchor(name)) = self.fetch_token()
1802                        else {
1803                            unreachable!("anchor token disappeared after peek")
1804                        };
1805                        anchor_id = self.register_anchor(name, &mark)?;
1806                        property_end = Some(mark.end);
1807                    }
1808                }
1809                if let Some(comment) = self.maybe_next_comment_event()? {
1810                    self.save_pending_node_properties(anchor_id, tag, tag_start, property_end);
1811                    return Ok(comment);
1812                }
1813            }
1814            _ => {}
1815        }
1816        match *self.peek_token()? {
1817            QueuedToken(mark, QueuedTokenType::BlockEntry) if indentless_sequence => {
1818                self.skip();
1819                let start = (
1820                    Event::SequenceStart(StructureStyle::Block, anchor_id, tag),
1821                    mark.with_tag_start(tag_start),
1822                );
1823                let comments = match self.next_comment_events() {
1824                    Ok(comments) => comments,
1825                    Err(error) if !matches!(error.kind(), ErrorKind::TooManyComments) => {
1826                        // `StrInput` can prove that a source has no comments and skips this
1827                        // lookahead, while streaming inputs must probe for one. If that probe
1828                        // discovers a later scanner error, the input backend must not determine
1829                        // whether this already-recognized sequence start is emitted first.
1830                        debug_assert!(self.deferred_error.is_none());
1831                        self.deferred_error = Some(error);
1832                        self.pending_empty_scalar_span = Some(mark);
1833                        self.state = State::IndentlessSequenceEntryNode;
1834                        return Ok(start);
1835                    }
1836                    Err(error) => return Err(error),
1837                };
1838                if comments.is_empty() {
1839                    self.pending_empty_scalar_span = Some(mark);
1840                    self.state = State::IndentlessSequenceEntryNode;
1841                    Ok(start)
1842                } else if let Ok(QueuedToken(
1843                    _,
1844                    QueuedTokenType::BlockEntry
1845                    | QueuedTokenType::Key
1846                    | QueuedTokenType::Value
1847                    | QueuedTokenType::BlockEnd,
1848                )) = self.peek_token()
1849                {
1850                    self.state = State::IndentlessSequenceEntry;
1851                    Ok(self.queue_two_events_by_span(
1852                        comments,
1853                        start,
1854                        (Event::empty_scalar(), mark),
1855                    ))
1856                } else {
1857                    self.pending_empty_scalar_span = Some(mark);
1858                    self.state = State::IndentlessSequenceEntryNode;
1859                    Ok(self.queue_event_by_span(comments, start))
1860                }
1861            }
1862            QueuedToken(_, QueuedTokenType::Scalar(..)) => {
1863                self.pop_state();
1864                let QueuedToken(mark, QueuedTokenType::Scalar(style, v)) = self.fetch_token()
1865                else {
1866                    unreachable!("scalar token disappeared after peek")
1867                };
1868                Ok(Self::attach_tag_start(
1869                    Event::Scalar(v, style, anchor_id, tag),
1870                    mark,
1871                    tag_start,
1872                ))
1873            }
1874            QueuedToken(mark, QueuedTokenType::FlowSequenceStart) => {
1875                self.state = State::FlowSequenceFirstEntry;
1876                self.skip();
1877                Ok(Self::attach_tag_start(
1878                    Event::SequenceStart(StructureStyle::Flow, anchor_id, tag),
1879                    mark,
1880                    tag_start,
1881                ))
1882            }
1883            QueuedToken(mark, QueuedTokenType::FlowMappingStart) => {
1884                self.state = State::FlowMappingFirstKey;
1885                self.skip();
1886                Ok(Self::attach_tag_start(
1887                    Event::MappingStart(StructureStyle::Flow, anchor_id, tag),
1888                    mark,
1889                    tag_start,
1890                ))
1891            }
1892            QueuedToken(mark, QueuedTokenType::BlockSequenceStart) if block => {
1893                self.state = State::BlockSequenceFirstEntry;
1894                self.skip();
1895                Ok(Self::attach_tag_start(
1896                    Event::SequenceStart(StructureStyle::Block, anchor_id, tag),
1897                    mark,
1898                    tag_start,
1899                ))
1900            }
1901            QueuedToken(mark, QueuedTokenType::BlockMappingStart) if block => {
1902                self.state = State::BlockMappingFirstKey;
1903                self.skip();
1904                Ok(Self::attach_tag_start(
1905                    Event::MappingStart(StructureStyle::Block, anchor_id, tag),
1906                    mark,
1907                    tag_start,
1908                ))
1909            }
1910            // ex 7.2, an empty scalar can follow a secondary tag
1911            QueuedToken(mark, _) if tag.is_some() || anchor_id > 0 => {
1912                self.pop_state();
1913                let span = property_end.map_or_else(|| Span::empty(mark.start), Span::empty);
1914                Ok(Self::attach_tag_start(
1915                    Event::empty_scalar_with_anchor(anchor_id, tag),
1916                    span,
1917                    tag_start,
1918                ))
1919            }
1920            QueuedToken(span, _) => {
1921                let kind = match self.state {
1922                    State::FlowSequenceFirstEntry | State::FlowSequenceEntry => {
1923                        ErrorKind::UnexpectedEofFlowSequence
1924                    }
1925                    State::FlowMappingFirstKey
1926                    | State::FlowMappingKey
1927                    | State::FlowMappingValue
1928                    | State::FlowMappingEmptyValue => ErrorKind::UnexpectedEofFlowMapping,
1929                    State::FlowSequenceEntryMappingKey
1930                    | State::FlowSequenceEntryMappingValue
1931                    | State::FlowSequenceEntryMappingEnd
1932                    | State::FlowNode => ErrorKind::UnexpectedEofImplicitFlowMapping,
1933                    State::BlockSequenceFirstEntry
1934                    | State::BlockSequenceEntry
1935                    | State::BlockNode => ErrorKind::UnexpectedEofBlockSequence,
1936                    State::BlockMappingFirstKey
1937                    | State::BlockMappingKey
1938                    | State::BlockMappingValue
1939                    | State::BlockNodeOrIndentlessSequence => ErrorKind::UnexpectedEofBlockMapping,
1940                    _ => ErrorKind::ExpectedNodeContent,
1941                };
1942                Err(ScanError::from_kind(span.start, kind))
1943            }
1944        }
1945    }
1946
1947    fn block_mapping_key<'a>(&mut self, _first: bool) -> ParseResult<'a>
1948    where
1949        'input: 'a,
1950    {
1951        match *self.peek_token()? {
1952            QueuedToken(_, QueuedTokenType::Key) => {
1953                // Indentation is only meaningful for block mapping keys.
1954                if let QueuedToken(key_span, QueuedTokenType::Key) = *self.peek_token()? {
1955                    self.pending_key_indent = Some(key_span.start.col());
1956                }
1957                self.skip();
1958                if let Some(comment) = self.maybe_next_comment_event()? {
1959                    self.state = State::BlockMappingKeyNode;
1960                    Ok(comment)
1961                } else {
1962                    self.block_mapping_key_node()
1963                }
1964            }
1965            // A missing block-mapping key before `:` is represented as an empty scalar.
1966            QueuedToken(mark, QueuedTokenType::Value) => {
1967                self.state = State::BlockMappingValue;
1968                Ok((Event::empty_scalar(), Span::empty(mark.start)))
1969            }
1970            QueuedToken(mark, QueuedTokenType::BlockEnd) => {
1971                self.pop_state();
1972                self.skip();
1973                Ok((Event::MappingEnd, mark))
1974            }
1975            QueuedToken(span, _) => Err(ScanError::from_kind(
1976                span.start,
1977                ErrorKind::ExpectedBlockMappingKey,
1978            )),
1979        }
1980    }
1981
1982    fn block_mapping_key_node<'a>(&mut self) -> ParseResult<'a>
1983    where
1984        'input: 'a,
1985    {
1986        if let QueuedToken(
1987            mark,
1988            QueuedTokenType::Key | QueuedTokenType::Value | QueuedTokenType::BlockEnd,
1989        ) = *self.peek_token()?
1990        {
1991            self.state = State::BlockMappingValue;
1992            Ok((Event::empty_scalar(), Span::empty(mark.start)))
1993        } else {
1994            self.defer_parse_node(
1995                State::BlockNodeOrIndentlessSequence,
1996                State::BlockMappingValue,
1997                true,
1998                true,
1999            )
2000        }
2001    }
2002
2003    fn block_mapping_value<'a>(&mut self) -> ParseResult<'a>
2004    where
2005        'input: 'a,
2006    {
2007        match *self.peek_token()? {
2008            QueuedToken(mark, QueuedTokenType::Value) => {
2009                self.skip();
2010                let comments = self.next_comment_events()?;
2011                if comments.is_empty() {
2012                    self.block_mapping_value_node_with_empty_span(mark)
2013                } else if let Ok(QueuedToken(
2014                    _,
2015                    QueuedTokenType::Key | QueuedTokenType::Value | QueuedTokenType::BlockEnd,
2016                )) = self.peek_token()
2017                {
2018                    self.state = State::BlockMappingKey;
2019                    Ok(self.queue_event_by_span(comments, (Event::empty_scalar(), mark)))
2020                } else {
2021                    self.pending_empty_scalar_span = Some(mark);
2022                    self.state = State::BlockMappingValueNode;
2023                    Ok(self.queue_tail_and_return_first(comments))
2024                }
2025            }
2026            QueuedToken(mark, _) => {
2027                self.state = State::BlockMappingKey;
2028                Ok((Event::empty_scalar(), Span::empty(mark.start)))
2029            }
2030        }
2031    }
2032
2033    fn block_mapping_value_node<'a>(&mut self) -> ParseResult<'a>
2034    where
2035        'input: 'a,
2036    {
2037        let Some(mark) = self.pending_empty_scalar_span.take() else {
2038            unreachable!(
2039                "block mapping value-node state entered without a pending empty-scalar span"
2040            )
2041        };
2042        self.block_mapping_value_node_with_empty_span(mark)
2043    }
2044
2045    fn block_mapping_value_node_with_empty_span<'a>(&mut self, mark: Span) -> ParseResult<'a>
2046    where
2047        'input: 'a,
2048    {
2049        if let QueuedToken(
2050            _,
2051            QueuedTokenType::Key | QueuedTokenType::Value | QueuedTokenType::BlockEnd,
2052        ) = *self.peek_token()?
2053        {
2054            self.state = State::BlockMappingKey;
2055            Ok((Event::empty_scalar(), mark))
2056        } else {
2057            self.defer_parse_node(
2058                State::BlockNodeOrIndentlessSequence,
2059                State::BlockMappingKey,
2060                true,
2061                true,
2062            )
2063        }
2064    }
2065
2066    fn flow_mapping_key<'a>(&mut self, first: bool) -> ParseResult<'a>
2067    where
2068        'input: 'a,
2069    {
2070        let span: Span =
2071            if let QueuedToken(mark, QueuedTokenType::FlowMappingEnd) = *self.peek_token()? {
2072                mark
2073            } else {
2074                if !first {
2075                    match *self.peek_token()? {
2076                        QueuedToken(_, QueuedTokenType::FlowEntry) => {
2077                            self.skip();
2078                            if let Some(comment) = self.maybe_next_comment_event()? {
2079                                self.state = State::FlowMappingFirstKey;
2080                                return Ok(comment);
2081                            }
2082                        }
2083                        QueuedToken(span, _) => {
2084                            return Err(ScanError::from_kind(
2085                                span.start,
2086                                ErrorKind::ExpectedFlowMappingSeparator,
2087                            ))
2088                        }
2089                    }
2090                }
2091
2092                match *self.peek_token()? {
2093                    QueuedToken(_, QueuedTokenType::Key) => {
2094                        self.skip();
2095                        if let Some(comment) = self.maybe_next_comment_event()? {
2096                            self.state = State::FlowMappingKeyNode;
2097                            return Ok(comment);
2098                        }
2099                        return self.flow_mapping_key_node();
2100                    }
2101                    QueuedToken(marker, QueuedTokenType::Value) => {
2102                        self.state = State::FlowMappingValue;
2103                        return Ok((Event::empty_scalar(), Span::empty(marker.start)));
2104                    }
2105                    QueuedToken(_, QueuedTokenType::FlowMappingEnd) => (),
2106                    _ => {
2107                        return self.defer_parse_node(
2108                            State::FlowNode,
2109                            State::FlowMappingEmptyValue,
2110                            false,
2111                            false,
2112                        );
2113                    }
2114                }
2115
2116                self.peek_token()?.0
2117            };
2118
2119        self.pop_state();
2120        self.skip();
2121        Ok((Event::MappingEnd, span))
2122    }
2123
2124    fn flow_mapping_key_node<'a>(&mut self) -> ParseResult<'a>
2125    where
2126        'input: 'a,
2127    {
2128        if let QueuedToken(
2129            mark,
2130            QueuedTokenType::Value | QueuedTokenType::FlowEntry | QueuedTokenType::FlowMappingEnd,
2131        ) = *self.peek_token()?
2132        {
2133            self.state = State::FlowMappingValue;
2134            Ok((Event::empty_scalar(), Span::empty(mark.start)))
2135        } else {
2136            self.defer_parse_node(State::FlowNode, State::FlowMappingValue, false, false)
2137        }
2138    }
2139
2140    fn flow_mapping_value<'a>(&mut self, empty: bool) -> ParseResult<'a>
2141    where
2142        'input: 'a,
2143    {
2144        let span: Span = {
2145            if empty {
2146                let QueuedToken(mark, _) = *self.peek_token()?;
2147                self.state = State::FlowMappingKey;
2148                return Ok((Event::empty_scalar(), Span::empty(mark.start)));
2149            }
2150            match *self.peek_token()? {
2151                QueuedToken(span, QueuedTokenType::Value) => {
2152                    self.skip();
2153                    let comments = self.next_comment_events()?;
2154                    if comments.is_empty() {
2155                        return self.flow_mapping_value_node_with_empty_span(span);
2156                    }
2157                    if let Ok(QueuedToken(
2158                        _,
2159                        QueuedTokenType::FlowEntry | QueuedTokenType::FlowMappingEnd,
2160                    )) = self.peek_token()
2161                    {
2162                        self.state = State::FlowMappingKey;
2163                        return Ok(
2164                            self.queue_event_by_span(comments, (Event::empty_scalar(), span))
2165                        );
2166                    }
2167
2168                    self.pending_empty_scalar_span = Some(span);
2169                    self.state = State::FlowMappingValueNode;
2170                    return Ok(self.queue_tail_and_return_first(comments));
2171                }
2172                QueuedToken(marker, _) => Span::empty(marker.start),
2173            }
2174        };
2175
2176        self.state = State::FlowMappingKey;
2177        Ok((Event::empty_scalar(), span))
2178    }
2179
2180    fn flow_mapping_value_node<'a>(&mut self) -> ParseResult<'a>
2181    where
2182        'input: 'a,
2183    {
2184        let Some(mark) = self.pending_empty_scalar_span.take() else {
2185            unreachable!(
2186                "flow mapping value-node state entered without a pending empty-scalar span"
2187            )
2188        };
2189        self.flow_mapping_value_node_with_empty_span(mark)
2190    }
2191
2192    fn flow_mapping_value_node_with_empty_span<'a>(&mut self, mark: Span) -> ParseResult<'a>
2193    where
2194        'input: 'a,
2195    {
2196        match self.peek_token()?.1 {
2197            QueuedTokenType::FlowEntry | QueuedTokenType::FlowMappingEnd => {
2198                self.state = State::FlowMappingKey;
2199                Ok((Event::empty_scalar(), mark))
2200            }
2201            _ => self.defer_parse_node(State::FlowNode, State::FlowMappingKey, false, false),
2202        }
2203    }
2204
2205    fn flow_sequence_entry<'a>(&mut self, first: bool) -> ParseResult<'a>
2206    where
2207        'input: 'a,
2208    {
2209        match *self.peek_token()? {
2210            QueuedToken(mark, QueuedTokenType::FlowSequenceEnd) => {
2211                self.pop_state();
2212                self.skip();
2213                return Ok((Event::SequenceEnd, mark));
2214            }
2215            QueuedToken(_, QueuedTokenType::FlowEntry) if !first => {
2216                self.skip();
2217                if let Some(comment) = self.maybe_next_comment_event()? {
2218                    self.state = State::FlowSequenceFirstEntry;
2219                    return Ok(comment);
2220                }
2221            }
2222            QueuedToken(span, _) if !first => {
2223                return Err(ScanError::from_kind(
2224                    span.start,
2225                    ErrorKind::ExpectedFlowSequenceSeparator,
2226                ));
2227            }
2228            _ => { /* next */ }
2229        }
2230        match *self.peek_token()? {
2231            QueuedToken(mark, QueuedTokenType::FlowSequenceEnd) => {
2232                self.pop_state();
2233                self.skip();
2234                Ok((Event::SequenceEnd, mark))
2235            }
2236            QueuedToken(mark, QueuedTokenType::Key) => {
2237                self.state = State::FlowSequenceEntryMappingKey;
2238                self.skip();
2239                Ok((Event::MappingStart(StructureStyle::Flow, 0, None), mark))
2240            }
2241            _ => self.defer_parse_node(State::FlowNode, State::FlowSequenceEntry, false, false),
2242        }
2243    }
2244
2245    fn indentless_sequence_entry<'a>(&mut self) -> ParseResult<'a>
2246    where
2247        'input: 'a,
2248    {
2249        match *self.peek_token()? {
2250            QueuedToken(mark, QueuedTokenType::BlockEntry) => {
2251                self.skip();
2252                let comments = self.next_comment_events()?;
2253                if comments.is_empty() {
2254                    self.indentless_sequence_entry_node_with_empty_span(mark)
2255                } else if let Ok(QueuedToken(
2256                    _,
2257                    QueuedTokenType::BlockEntry
2258                    | QueuedTokenType::Key
2259                    | QueuedTokenType::Value
2260                    | QueuedTokenType::BlockEnd,
2261                )) = self.peek_token()
2262                {
2263                    self.state = State::IndentlessSequenceEntry;
2264                    Ok(self.queue_event_by_span(comments, (Event::empty_scalar(), mark)))
2265                } else {
2266                    self.pending_empty_scalar_span = Some(mark);
2267                    self.state = State::IndentlessSequenceEntryNode;
2268                    Ok(self.queue_tail_and_return_first(comments))
2269                }
2270            }
2271            QueuedToken(mark, _) => {
2272                self.pop_state();
2273                Ok((Event::SequenceEnd, mark))
2274            }
2275        }
2276    }
2277
2278    fn indentless_sequence_entry_node<'a>(&mut self) -> ParseResult<'a>
2279    where
2280        'input: 'a,
2281    {
2282        let Some(mark) = self.pending_empty_scalar_span.take() else {
2283            unreachable!(
2284                "indentless sequence entry-node state entered without a pending empty-scalar span"
2285            )
2286        };
2287        self.indentless_sequence_entry_node_with_empty_span(mark)
2288    }
2289
2290    fn indentless_sequence_entry_node_with_empty_span<'a>(&mut self, mark: Span) -> ParseResult<'a>
2291    where
2292        'input: 'a,
2293    {
2294        if let QueuedToken(
2295            _,
2296            QueuedTokenType::BlockEntry
2297            | QueuedTokenType::Key
2298            | QueuedTokenType::Value
2299            | QueuedTokenType::BlockEnd,
2300        ) = *self.peek_token()?
2301        {
2302            self.state = State::IndentlessSequenceEntry;
2303            Ok((Event::empty_scalar(), mark))
2304        } else {
2305            self.defer_parse_node(
2306                State::BlockNode,
2307                State::IndentlessSequenceEntry,
2308                true,
2309                false,
2310            )
2311        }
2312    }
2313
2314    fn block_sequence_entry<'a>(&mut self, _first: bool) -> ParseResult<'a>
2315    where
2316        'input: 'a,
2317    {
2318        match *self.peek_token()? {
2319            QueuedToken(mark, QueuedTokenType::BlockEnd) => {
2320                self.pop_state();
2321                self.skip();
2322                Ok((Event::SequenceEnd, mark))
2323            }
2324            QueuedToken(mark, QueuedTokenType::BlockEntry) => {
2325                self.skip();
2326                let comments = self.next_comment_events()?;
2327                if comments.is_empty() {
2328                    self.block_sequence_entry_node_with_empty_span(mark)
2329                } else if let Ok(QueuedToken(
2330                    _,
2331                    QueuedTokenType::BlockEntry | QueuedTokenType::BlockEnd,
2332                )) = self.peek_token()
2333                {
2334                    self.state = State::BlockSequenceEntry;
2335                    Ok(self.queue_event_by_span(comments, (Event::empty_scalar(), mark)))
2336                } else {
2337                    self.pending_empty_scalar_span = Some(mark);
2338                    self.state = State::BlockSequenceEntryNode;
2339                    Ok(self.queue_tail_and_return_first(comments))
2340                }
2341            }
2342            QueuedToken(span, _) => Err(ScanError::from_kind(
2343                span.start,
2344                ErrorKind::ExpectedBlockSequenceEntry,
2345            )),
2346        }
2347    }
2348
2349    fn block_sequence_entry_node<'a>(&mut self) -> ParseResult<'a>
2350    where
2351        'input: 'a,
2352    {
2353        let Some(mark) = self.pending_empty_scalar_span.take() else {
2354            unreachable!(
2355                "block sequence entry-node state entered without a pending empty-scalar span"
2356            )
2357        };
2358        self.block_sequence_entry_node_with_empty_span(mark)
2359    }
2360
2361    fn block_sequence_entry_node_with_empty_span<'a>(&mut self, mark: Span) -> ParseResult<'a>
2362    where
2363        'input: 'a,
2364    {
2365        if let QueuedToken(_, QueuedTokenType::BlockEntry | QueuedTokenType::BlockEnd) =
2366            *self.peek_token()?
2367        {
2368            self.state = State::BlockSequenceEntry;
2369            Ok((Event::empty_scalar(), mark))
2370        } else {
2371            self.defer_parse_node(State::BlockNode, State::BlockSequenceEntry, true, false)
2372        }
2373    }
2374
2375    fn flow_sequence_entry_mapping_key<'a>(&mut self) -> ParseResult<'a>
2376    where
2377        'input: 'a,
2378    {
2379        if let QueuedToken(mark, QueuedTokenType::FlowEntry | QueuedTokenType::FlowSequenceEnd) =
2380            *self.peek_token()?
2381        {
2382            self.state = State::FlowSequenceEntryMappingValue;
2383            Ok((Event::empty_scalar(), Span::empty(mark.start)))
2384        } else {
2385            self.defer_parse_node(
2386                State::FlowNode,
2387                State::FlowSequenceEntryMappingValue,
2388                false,
2389                false,
2390            )
2391        }
2392    }
2393
2394    fn flow_sequence_entry_mapping_value<'a>(&mut self) -> ParseResult<'a>
2395    where
2396        'input: 'a,
2397    {
2398        match *self.peek_token()? {
2399            QueuedToken(_, QueuedTokenType::Value) => {
2400                self.skip();
2401                if let Some(comment) = self.maybe_next_comment_event()? {
2402                    self.state = State::FlowSequenceEntryMappingValueNode;
2403                    Ok(comment)
2404                } else {
2405                    self.flow_sequence_entry_mapping_value_node()
2406                }
2407            }
2408            QueuedToken(mark, _) => {
2409                self.state = State::FlowSequenceEntryMappingEnd;
2410                Ok((Event::empty_scalar(), Span::empty(mark.start)))
2411            }
2412        }
2413    }
2414
2415    fn flow_sequence_entry_mapping_value_node<'a>(&mut self) -> ParseResult<'a>
2416    where
2417        'input: 'a,
2418    {
2419        let QueuedToken(span, ref tok) = *self.peek_token()?;
2420        if matches!(
2421            tok,
2422            QueuedTokenType::FlowEntry | QueuedTokenType::FlowSequenceEnd
2423        ) {
2424            self.state = State::FlowSequenceEntryMappingEnd;
2425            Ok((Event::empty_scalar(), Span::empty(span.start)))
2426        } else {
2427            self.defer_parse_node(
2428                State::FlowNode,
2429                State::FlowSequenceEntryMappingEnd,
2430                false,
2431                false,
2432            )
2433        }
2434    }
2435
2436    #[allow(clippy::unnecessary_wraps)]
2437    fn flow_sequence_entry_mapping_end<'a>(&mut self) -> ParseResult<'a>
2438    where
2439        'input: 'a,
2440    {
2441        self.state = State::FlowSequenceEntry;
2442        let QueuedToken(span, _) = *self.peek_token()?;
2443        Ok((Event::MappingEnd, Span::empty(span.start)))
2444    }
2445
2446    /// Resolve a tag from the handle and the suffix.
2447    fn resolve_tag(
2448        &self,
2449        span: Span,
2450        handle: &Cow<'input, str>,
2451        suffix: Cow<'input, str>,
2452    ) -> Result<Cow<'input, Tag>, ScanError> {
2453        let original_handle = handle.to_string();
2454        let suffix = suffix.into_owned();
2455        let tag = if handle == "!!" {
2456            // "!!" is a shorthand for "tag:yaml.org,2002:". However, that default can be
2457            // overridden.
2458            Tag::with_original_handle(
2459                self.tags
2460                    .get("!!")
2461                    .map_or_else(|| "tag:yaml.org,2002:".to_string(), ToString::to_string),
2462                suffix,
2463                original_handle,
2464            )
2465        } else if handle.is_empty() && suffix == "!" {
2466            // "!" introduces a local tag. Local tags may have their prefix overridden.
2467            match self.tags.get("!") {
2468                Some(prefix) => {
2469                    Tag::with_original_handle(prefix.to_string(), suffix, original_handle)
2470                }
2471                None => Tag::with_original_handle(String::new(), suffix, original_handle),
2472            }
2473        } else {
2474            // Lookup handle in our tag directives.
2475            let prefix = self.tags.get(&**handle);
2476            if let Some(prefix) = prefix {
2477                Tag::with_original_handle(prefix.to_string(), suffix, original_handle)
2478            } else {
2479                // Otherwise, it may be a local handle. With a local handle, the handle is set to
2480                // "!" and the suffix to whatever follows it ("!foo" -> ("!", "foo")).
2481                // If the handle is of the form "!foo!", this cannot be a local handle and we need
2482                // to error.
2483                if handle.len() >= 2 && handle.starts_with('!') && handle.ends_with('!') {
2484                    return Err(ScanError::from_kind(
2485                        span.start,
2486                        ErrorKind::UndeclaredTagHandle,
2487                    ));
2488                }
2489                Tag::with_original_handle(handle.to_string(), suffix, original_handle)
2490            }
2491        };
2492        Ok(Cow::Owned(tag))
2493    }
2494}
2495
2496impl<'input, T: BorrowedInput<'input>> ParserTrait<'input> for Parser<'input, T> {
2497    fn peek(&mut self) -> Option<Result<&(Event<'input>, Span), ScanError>> {
2498        if let Some(ref x) = self.current {
2499            Some(Ok(x))
2500        } else if let Some(error) = &self.current_error {
2501            Some(Err(error.clone()))
2502        } else {
2503            if self.stream_end_emitted {
2504                return None;
2505            }
2506            match self.next_event_impl() {
2507                Ok(token) => self.current = Some(token),
2508                Err(error) => {
2509                    self.current_error = Some(error.clone());
2510                    return Some(Err(error));
2511                }
2512            }
2513            self.current.as_ref().map(Ok)
2514        }
2515    }
2516
2517    fn next_event(&mut self) -> Option<ParseResult<'input>> {
2518        if let Some(error) = self.current_error.take() {
2519            self.stream_end_emitted = true;
2520            return Some(Err(error));
2521        }
2522
2523        if self.stream_end_emitted {
2524            return None;
2525        }
2526
2527        let tok = self.next_event_impl();
2528        if matches!(tok, Ok((Event::StreamEnd, _)) | Err(_)) {
2529            self.stream_end_emitted = true;
2530        }
2531        Some(tok)
2532    }
2533
2534    fn load<R: SpannedEventReceiver<'input>>(
2535        &mut self,
2536        recv: &mut R,
2537        multi: bool,
2538    ) -> Result<(), ScanError> {
2539        let mut recv = InfallibleSpannedReceiver(recv);
2540        into_scan_result(ParserTrait::try_load(self, &mut recv, multi))
2541    }
2542
2543    fn try_load<R: TrySpannedEventReceiver<'input>>(
2544        &mut self,
2545        recv: &mut R,
2546        multi: bool,
2547    ) -> Result<(), TryLoadError<R::Error>> {
2548        let stream_start_buffered = matches!(self.current.as_ref(), Some((Event::StreamStart, _)));
2549        if !self.scanner.stream_started() || stream_start_buffered {
2550            let (ev, span) = self.next_event_impl()?;
2551            if ev != Event::StreamStart {
2552                return Err(TryLoadError::scan(ScanError::from_kind(
2553                    span.start,
2554                    ErrorKind::ExpectedStreamStart,
2555                )));
2556            }
2557            try_emit(recv, ev, span)?;
2558        }
2559
2560        let has_buffered_result = self.current.is_some()
2561            || self.current_error.is_some()
2562            || self.deferred_error.is_some()
2563            || !self.queued_events.is_empty();
2564        if self.scanner.stream_ended() && !has_buffered_result {
2565            // The scanner has already reached EOF before the document loop, so emit the terminal
2566            // event and stop.
2567            try_emit(recv, Event::StreamEnd, Span::empty(self.scanner.mark()))?;
2568            self.stream_end_emitted = true;
2569            return Ok(());
2570        }
2571
2572        loop {
2573            let (ev, span) = if let Some(error) = self.current_error.take() {
2574                self.stream_end_emitted = true;
2575                return Err(TryLoadError::scan(error));
2576            } else {
2577                self.next_event_impl()?
2578            };
2579            let is_doc_end = matches!(ev, Event::DocumentEnd);
2580            let is_stream_end = matches!(ev, Event::StreamEnd);
2581
2582            try_emit(recv, ev, span)?;
2583
2584            if is_stream_end {
2585                self.stream_end_emitted = true;
2586                return Ok(());
2587            }
2588            if !multi && is_doc_end {
2589                return Ok(());
2590            }
2591        }
2592    }
2593}
2594
2595impl<'input, T: BorrowedInput<'input>> Iterator for Parser<'input, T> {
2596    type Item = Result<(Event<'input>, Span), ScanError>;
2597
2598    fn next(&mut self) -> Option<Self::Item> {
2599        self.next_event()
2600    }
2601}
2602
2603impl<'input, T: BorrowedInput<'input>> core::iter::FusedIterator for Parser<'input, T> {}
2604
2605#[cfg(test)]
2606mod test {
2607    use alloc::{borrow::Cow, string::ToString, vec, vec::Vec};
2608    #[cfg(feature = "error_messages")]
2609    use alloc::{format, string::String};
2610    #[cfg(feature = "error_messages")]
2611    use core::{error::Error as _, fmt};
2612
2613    #[cfg(feature = "error_messages")]
2614    use crate::error::{ErrorKind, ScanError};
2615    use crate::scanner::{Marker, ScalarStyle, Span};
2616
2617    use super::{
2618        Event, EventReceiver, Parser, State, StructureStyle, Tag, TryEventReceiver, TryLoadError,
2619        TrySpannedEventReceiver, YamlVersion,
2620    };
2621
2622    #[derive(Default)]
2623    struct CollectingSink<'input> {
2624        events: Vec<Event<'input>>,
2625    }
2626
2627    impl<'input> EventReceiver<'input> for CollectingSink<'input> {
2628        fn on_event(&mut self, ev: Event<'input>) {
2629            self.events.push(ev);
2630        }
2631    }
2632
2633    #[cfg(feature = "error_messages")]
2634    fn first_error_info(input: &str) -> String {
2635        for event in Parser::new_from_str(input) {
2636            if let Err(err) = event {
2637                return err.info();
2638            }
2639        }
2640        panic!("expected parser error")
2641    }
2642
2643    fn first_tagged_scalar_tag(input: &str) -> Tag {
2644        Parser::new_from_str(input)
2645            .find_map(|event| match event.expect("input should parse").0 {
2646                Event::Scalar(_, _, _, Some(tag)) => Some(tag.into_owned()),
2647                _ => None,
2648            })
2649            .expect("expected tagged scalar")
2650    }
2651
2652    #[test]
2653    fn deferred_parse_node_can_emit_comment_before_flow_node() {
2654        let mut parser = Parser::new_from_str("---\n# deferred\nvalue\n");
2655        assert_eq!(parser.stream_start().unwrap().0, Event::StreamStart);
2656        assert_eq!(
2657            parser.document_start(true).unwrap().0,
2658            Event::DocumentStart(true, None)
2659        );
2660
2661        let (event, _) = parser
2662            .defer_parse_node(State::FlowNode, State::FlowMappingKey, false, false)
2663            .unwrap();
2664
2665        assert!(matches!(event, Event::Comment(text, _) if text == " deferred"));
2666        assert_eq!(parser.state, State::FlowNode);
2667    }
2668
2669    #[test]
2670    fn queued_node_event_gets_pending_key_indent() {
2671        let mut parser = Parser::new_from_str("");
2672        let span = Span::empty(Marker::new(0, 1, 0));
2673
2674        parser.pending_key_indent = Some(3);
2675        parser
2676            .queued_events
2677            .push_back((Event::SequenceStart(StructureStyle::Block, 0, None), span));
2678
2679        let (event, span) = parser.next_event_impl().unwrap();
2680
2681        assert!(matches!(
2682            event,
2683            Event::SequenceStart(StructureStyle::Block, 0, None)
2684        ));
2685        assert_eq!(span.indent, Some(3));
2686        assert_eq!(parser.pending_key_indent, None);
2687    }
2688
2689    #[test]
2690    fn state_machine_handles_deferred_flow_node_states() {
2691        let mut parser = Parser::new_from_str("value\n");
2692        assert_eq!(parser.stream_start().unwrap().0, Event::StreamStart);
2693        assert_eq!(
2694            parser.document_start(true).unwrap().0,
2695            Event::DocumentStart(false, None)
2696        );
2697        parser.state = State::FlowNode;
2698        parser.push_state(State::End);
2699
2700        let (event, _) = parser.state_machine().unwrap();
2701
2702        assert!(matches!(event, Event::Scalar(value, ..) if value == "value"));
2703
2704        let mut parser = Parser::new_from_str("value\n");
2705        assert_eq!(parser.stream_start().unwrap().0, Event::StreamStart);
2706        assert_eq!(
2707            parser.document_start(true).unwrap().0,
2708            Event::DocumentStart(false, None)
2709        );
2710        parser.state = State::FlowSequenceEntryMappingValueNode;
2711
2712        let (event, _) = parser.state_machine().unwrap();
2713
2714        assert!(matches!(event, Event::Scalar(value, ..) if value == "value"));
2715    }
2716
2717    #[test]
2718    fn display_resolved_core_tag_without_extra_bang() {
2719        let tag = Tag::with_original_handle("tag:yaml.org,2002:", "str", "!!");
2720
2721        assert_eq!(tag.to_string(), "tag:yaml.org,2002:str");
2722    }
2723
2724    #[test]
2725    fn tag_helpers_distinguish_core_and_local_tags() {
2726        let core = Tag::with_original_handle("tag:yaml.org,2002:", "int", "!!");
2727        let local = Tag::new("!", "thing");
2728        let non_specific = Tag::with_original_handle("", "!", "");
2729        let verbatim = Tag::with_original_handle("", "tag:example.com,2000:thing", "");
2730        let unknown_yaml_org = Tag::with_original_handle("", "tag:yaml.org,2002:application", "");
2731
2732        assert_eq!(core.core_suffix(), Some("int"));
2733        assert!(core.is_yaml_core_schema());
2734        assert!(core.is_yaml_core_schema_tag("int"));
2735        assert!(!core.is_yaml_core_schema_tag("str"));
2736        assert!(!core.is_custom());
2737        assert_eq!(core.parts(), ("tag:yaml.org,2002:", "int"));
2738        assert_eq!(core.original_parts(), ("!!", "int"));
2739        assert_eq!(core.original(), "!!int");
2740
2741        assert_eq!(local.core_suffix(), None);
2742        assert!(!local.is_yaml_core_schema());
2743        assert!(!local.is_yaml_core_schema_tag("thing"));
2744        assert!(local.is_custom());
2745        assert_eq!(local.parts(), ("!", "thing"));
2746        assert_eq!(local.original_parts(), ("!", "thing"));
2747        assert_eq!(local.original(), "!thing");
2748        assert_eq!(local.to_string(), "!thing");
2749
2750        assert_eq!(non_specific.parts(), ("", "!"));
2751        assert_eq!(non_specific.original_parts(), ("", "!"));
2752        assert_eq!(non_specific.original(), "!");
2753
2754        assert_eq!(verbatim.parts(), ("", "tag:example.com,2000:thing"));
2755        assert_eq!(
2756            verbatim.original_parts(),
2757            ("", "tag:example.com,2000:thing")
2758        );
2759        assert_eq!(verbatim.original(), "!<tag:example.com,2000:thing>");
2760
2761        assert_eq!(unknown_yaml_org.core_suffix(), None);
2762        assert!(!unknown_yaml_org.is_yaml_core_schema());
2763        assert!(unknown_yaml_org.is_custom());
2764    }
2765
2766    #[test]
2767    fn core_suffix_uses_resolved_tag_uri_for_common_spellings() {
2768        let cases = [
2769            ("shorthand", "v: !!int 1\n", ("tag:yaml.org,2002:", "int")),
2770            (
2771                "verbatim",
2772                "v: !<tag:yaml.org,2002:int> 1\n",
2773                ("", "tag:yaml.org,2002:int"),
2774            ),
2775            (
2776                "full prefix",
2777                "%TAG !e! tag:yaml.org,2002:\n---\nv: !e!int 1\n",
2778                ("tag:yaml.org,2002:", "int"),
2779            ),
2780            (
2781                "mid-split",
2782                "%TAG !m! tag:yaml.org,2002:i\n---\nv: !m!nt 1\n",
2783                ("tag:yaml.org,2002:i", "nt"),
2784            ),
2785        ];
2786
2787        for (label, input, expected_parts) in cases {
2788            let tag = first_tagged_scalar_tag(input);
2789
2790            assert_eq!(tag.parts(), expected_parts, "{label}");
2791            assert_eq!(tag.core_suffix(), Some("int"), "{label}");
2792            assert!(tag.is_yaml_core_schema(), "{label}");
2793            assert!(tag.is_yaml_core_schema_tag("int"), "{label}");
2794            assert!(!tag.is_yaml_core_schema_tag("str"), "{label}");
2795            assert!(!tag.is_custom(), "{label}");
2796        }
2797    }
2798
2799    #[test]
2800    fn core_suffix_rejects_non_core_yaml_org_tags() {
2801        let cases = [
2802            "binary",
2803            "merge",
2804            "omap",
2805            "pairs",
2806            "set",
2807            "timestamp",
2808            "value",
2809            "yaml",
2810        ];
2811
2812        for suffix in cases {
2813            let tag = Tag::with_original_handle("tag:yaml.org,2002:", suffix, "!!");
2814
2815            assert_eq!(tag.core_suffix(), None, "{suffix}");
2816            assert!(!tag.is_yaml_core_schema(), "{suffix}");
2817            assert!(tag.is_custom(), "{suffix}");
2818        }
2819    }
2820
2821    #[test]
2822    fn core_suffix_rejects_non_core_tags() {
2823        let cases = [
2824            ("local", "v: !local 1\n"),
2825            ("verbatim custom", "v: !<tag:example.com,2000:int> 1\n"),
2826            (
2827                "custom directive",
2828                "%TAG !e! tag:example.com,2000:\n---\nv: !e!int 1\n",
2829            ),
2830            (
2831                "overridden secondary handle",
2832                "%TAG !! tag:example.com,2000:app/\n---\nv: !!int 1\n",
2833            ),
2834        ];
2835
2836        for (label, input) in cases {
2837            let tag = first_tagged_scalar_tag(input);
2838
2839            assert_eq!(tag.core_suffix(), None, "{label}");
2840            assert!(!tag.is_yaml_core_schema(), "{label}");
2841            assert!(!tag.is_yaml_core_schema_tag("int"), "{label}");
2842            assert!(tag.is_custom(), "{label}");
2843        }
2844    }
2845
2846    #[test]
2847    fn suffix_in_namespace_resolves_across_spellings() {
2848        const NS: &str = "tag:yaml.org,2002:";
2849
2850        // Every spelling of `tag:yaml.org,2002:omap` resolves to the same name, even though
2851        // `omap` is not a Core Schema type (so `core_suffix` reports `None`). `mid_split` cuts
2852        // the URI after the namespace prefix (handle longer than `NS`); `inside_split` cuts it
2853        // before the prefix ends (handle a non-empty prefix of `NS`), exercising both branches.
2854        let shorthand = Tag::with_original_handle(NS, "omap", "!!");
2855        let verbatim = Tag::with_original_handle("", "tag:yaml.org,2002:omap", "");
2856        let mid_split = Tag::with_original_handle("tag:yaml.org,2002:o", "map", "!o!");
2857        let inside_split = Tag::with_original_handle("tag:yaml.org,", "2002:omap", "!y!");
2858        for tag in [&shorthand, &verbatim, &mid_split, &inside_split] {
2859            assert_eq!(tag.suffix_in_namespace(NS).as_deref(), Some("omap"));
2860            assert_eq!(tag.core_suffix(), None);
2861        }
2862
2863        // Borrow whenever the resolved name is a contiguous slice of `handle` or `suffix`;
2864        // allocate only when a split lands inside the name itself (handle extends past `NS`).
2865        assert!(matches!(
2866            shorthand.suffix_in_namespace(NS),
2867            Some(Cow::Borrowed(_))
2868        ));
2869        assert!(matches!(
2870            verbatim.suffix_in_namespace(NS),
2871            Some(Cow::Borrowed(_))
2872        ));
2873        assert!(matches!(
2874            inside_split.suffix_in_namespace(NS),
2875            Some(Cow::Borrowed(_))
2876        ));
2877        assert!(matches!(
2878            mid_split.suffix_in_namespace(NS),
2879            Some(Cow::Owned(_))
2880        ));
2881
2882        // The non-core `merge` type resolves the same way; core types still flow through
2883        // `core_suffix`.
2884        let merge = Tag::with_original_handle(NS, "merge", "!!");
2885        assert_eq!(merge.suffix_in_namespace(NS).as_deref(), Some("merge"));
2886        assert_eq!(merge.core_suffix(), None);
2887        assert_eq!(
2888            Tag::new(NS, "int").suffix_in_namespace(NS).as_deref(),
2889            Some("int")
2890        );
2891
2892        // Tags outside the namespace do not resolve into it.
2893        assert_eq!(Tag::new("!", "omap").suffix_in_namespace(NS), None);
2894        assert_eq!(
2895            Tag::with_original_handle("", "tag:example.com,2000:omap", "").suffix_in_namespace(NS),
2896            None
2897        );
2898    }
2899
2900    #[test]
2901    fn attach_tag_start_applies_marker_to_span() {
2902        let event = Event::Scalar("value".into(), ScalarStyle::Plain, 0, None);
2903        let span = Span::new(Marker::new(6, 1, 6), Marker::new(11, 1, 11));
2904        let tag_start = Marker::new(0, 1, 0);
2905
2906        let (attached_event, attached_span) =
2907            Parser::<crate::input::str::StrInput<'_>>::attach_tag_start(
2908                event.clone(),
2909                span,
2910                Some(tag_start),
2911            );
2912
2913        assert_eq!(attached_event, event);
2914        assert_eq!(attached_span.start, span.start);
2915        assert_eq!(attached_span.end, span.end);
2916        assert_eq!(attached_span.tag_start(), Some(tag_start));
2917    }
2918
2919    #[test]
2920    fn event_inspection_helpers_report_node_metadata() {
2921        let tag = Tag::new("!", "thing");
2922        let scalar = Event::Scalar(
2923            "value".into(),
2924            ScalarStyle::DoubleQuoted,
2925            7,
2926            Some(Cow::Borrowed(&tag)),
2927        );
2928        let sequence =
2929            Event::SequenceStart(StructureStyle::Block, 8, Some(Cow::Owned(tag.clone())));
2930        let mapping = Event::MappingStart(StructureStyle::Block, 9, Some(Cow::Borrowed(&tag)));
2931
2932        assert_eq!(scalar.anchor_id(), Some(7));
2933        assert_eq!(scalar.alias_id(), None);
2934        assert_eq!(scalar.tag(), Some(&tag));
2935        assert_eq!(scalar.scalar(), Some(("value", ScalarStyle::DoubleQuoted)));
2936        assert!(scalar.is_node());
2937
2938        assert_eq!(sequence.anchor_id(), Some(8));
2939        assert_eq!(sequence.alias_id(), None);
2940        assert_eq!(sequence.tag(), Some(&tag));
2941        assert_eq!(sequence.scalar(), None);
2942        assert!(sequence.is_node());
2943
2944        assert_eq!(mapping.anchor_id(), Some(9));
2945        assert_eq!(mapping.alias_id(), None);
2946        assert_eq!(mapping.tag(), Some(&tag));
2947        assert_eq!(mapping.scalar(), None);
2948        assert!(mapping.is_node());
2949
2950        let alias = Event::Alias(10);
2951        assert_eq!(alias.anchor_id(), None);
2952        assert_eq!(alias.alias_id(), Some(10));
2953        assert_eq!(alias.tag(), None);
2954        assert_eq!(alias.scalar(), None);
2955        assert!(alias.is_node());
2956
2957        let unanchored_scalar = Event::Scalar("x".into(), ScalarStyle::Plain, 0, None);
2958        assert_eq!(unanchored_scalar.anchor_id(), None);
2959        assert_eq!(unanchored_scalar.alias_id(), None);
2960
2961        let stream_start = Event::StreamStart;
2962        assert_eq!(stream_start.anchor_id(), None);
2963        assert_eq!(stream_start.alias_id(), None);
2964        assert_eq!(stream_start.tag(), None);
2965        assert_eq!(stream_start.scalar(), None);
2966        assert!(!stream_start.is_node());
2967    }
2968
2969    #[test]
2970    fn test_peek_eq_parse() {
2971        let s = "
2972a0 bb: val
2973a1: &x
2974    b1: 4
2975    b2: d
2976a2: 4
2977a3: [1, 2, 3]
2978a4:
2979    - [a1, a2]
2980    - 2
2981a5: *x
2982";
2983        let mut p = Parser::new_from_str(s);
2984        loop {
2985            let event_peek = p.peek().unwrap().unwrap().clone();
2986            let event = p.next_event().unwrap().unwrap();
2987            assert_eq!(event, event_peek);
2988            if event.0 == Event::StreamEnd {
2989                break;
2990            }
2991        }
2992    }
2993
2994    #[test]
2995    fn test_repeated_peek_returns_buffered_event() {
2996        let mut parser = Parser::new_from_str("key: value\n");
2997
2998        let first_peek = parser.peek().unwrap().unwrap().clone();
2999        let second_peek = parser.peek().unwrap().unwrap().clone();
3000        let next = parser.next_event().unwrap().unwrap();
3001
3002        assert_eq!(first_peek, second_peek);
3003        assert_eq!(first_peek, next);
3004    }
3005
3006    #[cfg(feature = "error_messages")]
3007    #[test]
3008    fn test_peek_surfaces_scan_error_without_consuming_stream_end_state() {
3009        let mut parser = Parser::new_from_str("a: [1, 2");
3010
3011        loop {
3012            match parser.peek() {
3013                Some(Ok(_)) => {
3014                    parser.next_event().unwrap().unwrap();
3015                }
3016                Some(Err(error)) => {
3017                    assert_eq!(error.info(), "unclosed bracket '['");
3018                    break;
3019                }
3020                None => panic!("expected parse error"),
3021            }
3022        }
3023    }
3024
3025    #[test]
3026    fn test_iterator_terminates_after_scan_error() {
3027        let parser = Parser::new_from_str("foo:\n  bar\ninvalid\n");
3028        let mut errors = 0usize;
3029        let mut events = 0usize;
3030
3031        for item in parser {
3032            events += 1;
3033            if item.is_err() {
3034                errors += 1;
3035            }
3036            assert!(
3037                events < 1000,
3038                "parser iterator did not terminate after a scan error"
3039            );
3040        }
3041
3042        assert_eq!(errors, 1);
3043    }
3044
3045    #[cfg(feature = "error_messages")]
3046    #[test]
3047    fn test_iterator_terminates_after_node_property_error() {
3048        let parser = Parser::new_from_str("- *nope\n- 2\n");
3049        let mut errors = 0usize;
3050        let mut saw_later_node = false;
3051        let mut events = 0usize;
3052
3053        for item in parser {
3054            events += 1;
3055            match item {
3056                Ok((Event::Scalar(value, ..), _)) if value == "2" => saw_later_node = true,
3057                Ok(_) => {}
3058                Err(error) => {
3059                    assert_eq!(error.info(), "while parsing node, found unknown anchor");
3060                    errors += 1;
3061                }
3062            }
3063            assert!(
3064                events < 1000,
3065                "parser iterator did not terminate after a node-property error"
3066            );
3067        }
3068
3069        assert_eq!(errors, 1);
3070        assert!(!saw_later_node, "parser resumed after the alias error");
3071    }
3072
3073    #[test]
3074    fn test_peeked_scan_error_is_returned_once_by_next_event() {
3075        let mut parser = Parser::new_from_str("a: [1, 2");
3076
3077        let first_error = loop {
3078            match parser.peek() {
3079                Some(Ok(_)) => {
3080                    parser.next_event().unwrap().unwrap();
3081                }
3082                Some(Err(error)) => break error,
3083                None => panic!("expected parse error"),
3084            }
3085        };
3086        let Some(Err(second_error)) = parser.peek() else {
3087            panic!("expected cached parse error");
3088        };
3089
3090        assert_eq!(first_error, second_error);
3091        assert_eq!(parser.next_event().unwrap().unwrap_err(), first_error);
3092        assert!(parser.next_event().is_none());
3093        assert!(parser.peek().is_none());
3094    }
3095
3096    #[cfg(feature = "error_messages")]
3097    #[test]
3098    fn test_peeked_node_property_error_is_stable_and_terminal() {
3099        let mut parser = Parser::new_from_str("a: *nope\nb: 2\n");
3100
3101        for _ in 0..4 {
3102            parser.next_event().unwrap().unwrap();
3103        }
3104
3105        let Some(Err(first_error)) = parser.peek() else {
3106            panic!("expected unknown alias error");
3107        };
3108        let Some(Err(second_error)) = parser.peek() else {
3109            panic!("expected cached unknown alias error");
3110        };
3111
3112        assert_eq!(first_error, second_error);
3113        assert_eq!(
3114            first_error.info(),
3115            "while parsing node, found unknown anchor"
3116        );
3117        assert_eq!(parser.next_event().unwrap().unwrap_err(), first_error);
3118        assert!(parser.next_event().is_none());
3119        assert!(parser.peek().is_none());
3120    }
3121
3122    #[test]
3123    fn test_peek_and_next_return_none_after_stream_end() {
3124        let mut parser = Parser::new_from_str("");
3125
3126        assert!(matches!(
3127            parser.next_event().unwrap().unwrap().0,
3128            Event::StreamStart
3129        ));
3130        assert!(matches!(
3131            parser.next_event().unwrap().unwrap().0,
3132            Event::StreamEnd
3133        ));
3134        assert!(parser.next_event().is_none());
3135        assert!(parser.peek().is_none());
3136    }
3137
3138    #[test]
3139    fn test_load_after_stream_already_ended_emits_stream_end() {
3140        let mut parser = Parser::new_from_str("");
3141        while parser.next_event().is_some() {}
3142
3143        let mut sink = CollectingSink::default();
3144        parser.load(&mut sink, true).unwrap();
3145
3146        assert_eq!(sink.events, vec![Event::StreamEnd]);
3147    }
3148
3149    #[test]
3150    fn test_load_full_stream_fuses_iterator_after_stream_end() {
3151        let mut parser = Parser::new_from_str("a: 1\n");
3152        let mut sink = CollectingSink::default();
3153
3154        parser.load(&mut sink, true).unwrap();
3155
3156        assert!(matches!(sink.events.last(), Some(Event::StreamEnd)));
3157        assert!(parser.next_event().is_none());
3158        assert!(parser.peek().is_none());
3159    }
3160
3161    #[test]
3162    fn test_load_after_peek_delivers_buffered_document_end_before_stream_end() {
3163        let mut parser = Parser::new_from_str("a");
3164        for _ in 0..3 {
3165            parser.next_event().unwrap().unwrap();
3166        }
3167
3168        assert_eq!(parser.peek().unwrap().unwrap().0, Event::DocumentEnd);
3169
3170        let mut sink = CollectingSink::default();
3171        parser.load(&mut sink, true).unwrap();
3172
3173        assert_eq!(sink.events, vec![Event::DocumentEnd, Event::StreamEnd]);
3174        assert!(parser.next_event().is_none());
3175    }
3176
3177    #[test]
3178    fn test_load_visits_nested_collection_events() {
3179        let mut parser = Parser::new_from_str("root:\n  - item: value\n  - [a, b]\n");
3180        let mut sink = CollectingSink::default();
3181
3182        parser.load(&mut sink, true).unwrap();
3183
3184        assert_eq!(
3185            sink.events,
3186            vec![
3187                Event::StreamStart,
3188                Event::DocumentStart(false, None),
3189                Event::MappingStart(StructureStyle::Block, 0, None),
3190                Event::Scalar("root".into(), ScalarStyle::Plain, 0, None),
3191                Event::SequenceStart(StructureStyle::Block, 0, None),
3192                Event::MappingStart(StructureStyle::Block, 0, None),
3193                Event::Scalar("item".into(), ScalarStyle::Plain, 0, None),
3194                Event::Scalar("value".into(), ScalarStyle::Plain, 0, None),
3195                Event::MappingEnd,
3196                Event::SequenceStart(StructureStyle::Flow, 0, None),
3197                Event::Scalar("a".into(), ScalarStyle::Plain, 0, None),
3198                Event::Scalar("b".into(), ScalarStyle::Plain, 0, None),
3199                Event::SequenceEnd,
3200                Event::SequenceEnd,
3201                Event::MappingEnd,
3202                Event::DocumentEnd,
3203                Event::StreamEnd,
3204            ]
3205        );
3206    }
3207
3208    #[derive(Clone, Debug, PartialEq, Eq)]
3209    enum ValidationError {
3210        ForbiddenValue,
3211    }
3212
3213    #[cfg(feature = "error_messages")]
3214    #[derive(Debug)]
3215    struct ReceiverFailure;
3216
3217    #[cfg(feature = "error_messages")]
3218    impl fmt::Display for ReceiverFailure {
3219        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3220            write!(f, "receiver failed")
3221        }
3222    }
3223
3224    #[cfg(feature = "error_messages")]
3225    impl core::error::Error for ReceiverFailure {}
3226
3227    struct FailingSink<'input> {
3228        events: Vec<Event<'input>>,
3229    }
3230
3231    impl<'input> TryEventReceiver<'input> for FailingSink<'input> {
3232        type Error = ValidationError;
3233
3234        fn on_event(&mut self, ev: Event<'input>) -> Result<(), Self::Error> {
3235            let should_fail = matches!(&ev, Event::Scalar(value, ..) if value.as_ref() == "bad");
3236            self.events.push(ev);
3237            if should_fail {
3238                Err(ValidationError::ForbiddenValue)
3239            } else {
3240                Ok(())
3241            }
3242        }
3243    }
3244
3245    #[test]
3246    fn test_try_load_stops_on_receiver_error() {
3247        let mut parser = Parser::new_from_str("ok: bad\nafter: value\n");
3248        let mut sink = FailingSink { events: Vec::new() };
3249
3250        let err = parser.try_load(&mut sink, true).unwrap_err();
3251
3252        assert_eq!(err, TryLoadError::Receiver(ValidationError::ForbiddenValue));
3253        assert!(sink
3254            .events
3255            .iter()
3256            .any(|event| matches!(event, Event::Scalar(value, ..) if value == "ok")));
3257        assert!(sink
3258            .events
3259            .iter()
3260            .any(|event| matches!(event, Event::Scalar(value, ..) if value == "bad")));
3261        assert!(!sink
3262            .events
3263            .iter()
3264            .any(|event| matches!(event, Event::Scalar(value, ..) if value == "after")));
3265    }
3266
3267    struct SpannedFailingSink {
3268        failed_span: Option<Span>,
3269    }
3270
3271    impl<'input> TrySpannedEventReceiver<'input> for SpannedFailingSink {
3272        type Error = Span;
3273
3274        fn on_event(&mut self, ev: Event<'input>, span: Span) -> Result<(), Self::Error> {
3275            if matches!(ev, Event::Scalar(value, ..) if value.as_ref() == "bad") {
3276                self.failed_span = Some(span);
3277                Err(span)
3278            } else {
3279                Ok(())
3280            }
3281        }
3282    }
3283
3284    #[test]
3285    fn test_try_load_spanned_receiver_gets_span() {
3286        let mut parser = Parser::new_from_str("value: bad\n");
3287        let mut sink = SpannedFailingSink { failed_span: None };
3288
3289        let err = parser.try_load(&mut sink, false).unwrap_err();
3290
3291        let TryLoadError::Receiver(span) = err else {
3292            panic!("expected receiver error");
3293        };
3294
3295        assert_eq!(Some(span), sink.failed_span);
3296        assert!(!span.is_empty());
3297    }
3298
3299    #[cfg(feature = "error_messages")]
3300    struct NeverFails {
3301        count: usize,
3302    }
3303
3304    #[cfg(feature = "error_messages")]
3305    impl<'input> TryEventReceiver<'input> for NeverFails {
3306        type Error = ValidationError;
3307
3308        fn on_event(&mut self, _ev: Event<'input>) -> Result<(), Self::Error> {
3309            self.count += 1;
3310            Ok(())
3311        }
3312    }
3313
3314    #[cfg(feature = "error_messages")]
3315    #[test]
3316    fn test_try_load_returns_scan_error() {
3317        let mut parser = Parser::new_from_str("%YAML 1.2\n%YAML 1.2\n---\n");
3318        let mut sink = NeverFails { count: 0 };
3319
3320        let err = parser.try_load(&mut sink, true).unwrap_err();
3321
3322        let TryLoadError::Scan(err) = err else {
3323            panic!("expected scan error");
3324        };
3325        assert_eq!(err.kind(), &ErrorKind::DuplicateVersionDirective);
3326        assert_eq!(err.info(), "duplicate version directive");
3327    }
3328
3329    #[cfg(feature = "error_messages")]
3330    #[test]
3331    fn test_try_load_error_display_and_source_cover_both_variants() {
3332        let scan = ScanError::from_kind(Marker::new(3, 1, 3), ErrorKind::UnexpectedEof);
3333        let scan_err: TryLoadError<ReceiverFailure> = scan.into();
3334
3335        assert!(scan_err
3336            .to_string()
3337            .starts_with("parser error: unexpected eof"));
3338        assert!(scan_err.source().is_some());
3339
3340        let receiver_err = TryLoadError::Receiver(ReceiverFailure);
3341
3342        assert_eq!(receiver_err.to_string(), "receiver error: receiver failed");
3343        assert!(receiver_err.source().is_some());
3344    }
3345
3346    #[cfg(feature = "error_messages")]
3347    #[test]
3348    fn test_try_load_requires_buffered_stream_start() {
3349        let mut parser = Parser::new_from_str("");
3350        let span = Span::empty(Marker::new(0, 1, 0));
3351        parser.current = Some((
3352            Event::Scalar("value".into(), ScalarStyle::Plain, 0, None),
3353            span,
3354        ));
3355        let mut sink = NeverFails { count: 0 };
3356
3357        let err = parser.try_load(&mut sink, true).unwrap_err();
3358
3359        let TryLoadError::Scan(err) = err else {
3360            panic!("expected scan error");
3361        };
3362        assert_eq!(err.info(), "did not find expected <stream-start>");
3363    }
3364
3365    #[test]
3366    fn test_try_load_after_stream_already_ended_emits_stream_end() {
3367        let mut parser = Parser::new_from_str("");
3368        while parser.next_event().is_some() {}
3369
3370        let mut sink = FailingSink { events: Vec::new() };
3371        parser.try_load(&mut sink, true).unwrap();
3372
3373        assert_eq!(sink.events, vec![Event::StreamEnd]);
3374    }
3375
3376    #[test]
3377    fn test_try_load_full_stream_fuses_iterator_after_stream_end() {
3378        let mut parser = Parser::new_from_str("a: 1\n");
3379        let mut sink = FailingSink { events: Vec::new() };
3380
3381        parser.try_load(&mut sink, true).unwrap();
3382
3383        assert!(matches!(sink.events.last(), Some(Event::StreamEnd)));
3384        assert!(parser.next_event().is_none());
3385        assert!(parser.peek().is_none());
3386    }
3387
3388    #[test]
3389    fn test_try_load_after_peek_delivers_buffered_document_end_before_stream_end() {
3390        let mut parser = Parser::new_from_str("a");
3391        for _ in 0..3 {
3392            parser.next_event().unwrap().unwrap();
3393        }
3394
3395        assert_eq!(parser.peek().unwrap().unwrap().0, Event::DocumentEnd);
3396
3397        let mut sink = FailingSink { events: Vec::new() };
3398        parser.try_load(&mut sink, true).unwrap();
3399
3400        assert_eq!(sink.events, vec![Event::DocumentEnd, Event::StreamEnd]);
3401        assert!(parser.next_event().is_none());
3402    }
3403
3404    #[test]
3405    fn test_load_single_document_stops_before_next_document() {
3406        let mut parser = Parser::new_from_str("a: 1\n---\nb: 2\n");
3407        let mut sink = CollectingSink::default();
3408
3409        parser.load(&mut sink, false).unwrap();
3410
3411        assert!(sink
3412            .events
3413            .iter()
3414            .any(|event| matches!(event, Event::Scalar(value, ..) if value == "a")));
3415        assert!(!sink
3416            .events
3417            .iter()
3418            .any(|event| matches!(event, Event::Scalar(value, ..) if value == "b")));
3419        assert!(matches!(sink.events.last(), Some(Event::DocumentEnd)));
3420    }
3421
3422    #[cfg(feature = "error_messages")]
3423    #[test]
3424    fn test_duplicate_version_directive_errors() {
3425        assert_eq!(
3426            first_error_info("%YAML 1.2\n%YAML 1.2\n---\n"),
3427            "duplicate version directive"
3428        );
3429    }
3430
3431    #[cfg(feature = "error_messages")]
3432    #[test]
3433    fn test_unsupported_yaml_major_version_errors() {
3434        assert_eq!(
3435            first_error_info("%YAML 9.9\n--- a\n"),
3436            "unsupported YAML major version"
3437        );
3438    }
3439
3440    #[test]
3441    fn test_document_start_emits_yaml_version() {
3442        let events = Parser::new_from_str("%YAML 1.2\n---\nvalue\n")
3443            .map(|event| event.unwrap().0)
3444            .collect::<Vec<_>>();
3445
3446        assert!(matches!(
3447            events.get(1),
3448            Some(Event::DocumentStart(
3449                true,
3450                Some(YamlVersion { major: 1, minor: 2 })
3451            ))
3452        ));
3453    }
3454
3455    #[test]
3456    fn test_document_start_allows_supported_major_future_minor_version() {
3457        let events = Parser::new_from_str("%YAML 1.9\n---\nvalue\n")
3458            .map(|event| event.unwrap().0)
3459            .collect::<Vec<_>>();
3460
3461        assert!(matches!(
3462            events.get(1),
3463            Some(Event::DocumentStart(
3464                true,
3465                Some(YamlVersion { major: 1, minor: 9 })
3466            ))
3467        ));
3468    }
3469
3470    #[test]
3471    fn test_document_start_keeps_version_and_tags_across_comment() {
3472        let events = Parser::new_from_str(
3473            "%YAML 1.2\n# directive comment\n%TAG !e! tag:example.com,2026:\n---\nkey: !e!thing value\n",
3474        )
3475        .map(|event| event.unwrap().0)
3476        .collect::<Vec<_>>();
3477
3478        assert!(matches!(
3479            events.get(2),
3480            Some(Event::DocumentStart(
3481                true,
3482                Some(YamlVersion { major: 1, minor: 2 })
3483            ))
3484        ));
3485
3486        let tag = events
3487            .iter()
3488            .find_map(|event| match event {
3489                Event::Scalar(value, _, _, Some(tag)) if value == "value" => Some(tag),
3490                _ => None,
3491            })
3492            .expect("expected tagged scalar after comment-separated directives");
3493
3494        assert_eq!(tag.handle, "tag:example.com,2026:");
3495        assert_eq!(tag.suffix, "thing");
3496    }
3497
3498    #[test]
3499    fn tag_directive_state_borrows_str_input_across_comment() {
3500        let mut parser = Parser::new_from_str(
3501            "%TAG !e! tag:example.com,2026:\n# directive comment\n---\nkey: value\n",
3502        );
3503
3504        while let Some(event) = parser.next_event() {
3505            if matches!(event.unwrap().0, Event::Comment(..)) {
3506                break;
3507            }
3508        }
3509
3510        assert!(matches!(
3511            parser.tags.get("!e!"),
3512            Some(Cow::Borrowed("tag:example.com,2026:"))
3513        ));
3514        assert!(parser
3515            .pending_document_tag_handles
3516            .iter()
3517            .any(|handle| matches!(handle, Cow::Borrowed("!e!"))));
3518    }
3519
3520    #[test]
3521    fn test_each_document_can_declare_own_yaml_version() {
3522        let document_starts = Parser::new_from_str(
3523            "%YAML 1.2\n---\na\n...\n%YAML 1.2\n---\nb\n...\n%YAML 1.1\n---\nc\n",
3524        )
3525        .filter_map(|event| match event.unwrap().0 {
3526            Event::DocumentStart(explicit, version) => Some((explicit, version)),
3527            _ => None,
3528        })
3529        .collect::<Vec<_>>();
3530
3531        assert_eq!(
3532            document_starts,
3533            vec![
3534                (true, Some(YamlVersion::new(1, 2))),
3535                (true, Some(YamlVersion::new(1, 2))),
3536                (true, Some(YamlVersion::new(1, 1))),
3537            ]
3538        );
3539    }
3540
3541    #[cfg(feature = "error_messages")]
3542    #[test]
3543    fn test_duplicate_tag_directive_errors() {
3544        assert_eq!(
3545            first_error_info("%TAG !t! tag:test,2024:\n%TAG !t! tag:other,2024:\n---\n"),
3546            "the TAG directive must only be given at most once per handle in the same document"
3547        );
3548    }
3549
3550    #[cfg(feature = "error_messages")]
3551    #[test]
3552    fn duplicate_tag_directive_across_comment_is_rejected() {
3553        let input = concat!(
3554            "%TAG !e! tag:example.com,2000:one/\n",
3555            "# separator\n",
3556            "%TAG !e! tag:example.com,2000:two/\n",
3557            "---\n",
3558        );
3559
3560        assert_eq!(
3561            first_error_info(input),
3562            "the TAG directive must only be given at most once per handle in the same document"
3563        );
3564    }
3565
3566    #[test]
3567    fn test_keep_tags_inherited_handle_can_be_redeclared_in_next_document() {
3568        let input = concat!(
3569            "%TAG !e! tag:example.com,2000:one/\n",
3570            "---\n",
3571            "first: !e!thing value\n",
3572            "...\n",
3573            "%TAG !e! tag:example.com,2000:two/\n",
3574            "---\n",
3575            "second: !e!thing value\n",
3576        );
3577
3578        let tags = Parser::new_from_str(input)
3579            .keep_tags(true)
3580            .filter_map(|event| match event.expect("input should parse").0 {
3581                Event::Scalar(value, _, _, Some(tag)) if value == "value" => {
3582                    Some(tag.handle.clone())
3583                }
3584                _ => None,
3585            })
3586            .collect::<Vec<_>>();
3587
3588        assert_eq!(
3589            tags,
3590            vec!["tag:example.com,2000:one/", "tag:example.com,2000:two/"]
3591        );
3592    }
3593
3594    #[cfg(feature = "error_messages")]
3595    #[test]
3596    fn test_directive_after_implicit_document_requires_explicit_end() {
3597        assert_eq!(
3598            first_error_info("---\nkey: value\n%YAML 1.2\n---\n"),
3599            "missing explicit document end marker before directive"
3600        );
3601    }
3602
3603    #[cfg(feature = "error_messages")]
3604    #[test]
3605    fn test_anchor_offset_overflow_reports_error() {
3606        let mut parser = Parser::new_from_str("&a value");
3607        parser.set_anchor_offset(usize::MAX);
3608
3609        let err = parser
3610            .find_map(Result::err)
3611            .expect("anchor registration should overflow");
3612
3613        assert_eq!(
3614            err.info(),
3615            "while parsing anchor, anchor count exceeded supported limit"
3616        );
3617    }
3618
3619    #[test]
3620    fn test_alias_resolves_to_registered_anchor_id() {
3621        let events = Parser::new_from_str("- &a value\n- *a\n")
3622            .map(|event| event.unwrap().0)
3623            .collect::<Vec<_>>();
3624
3625        assert!(events.iter().any(|event| matches!(event, Event::Alias(1))));
3626    }
3627
3628    #[test]
3629    fn test_anchor_then_tag_applies_both_to_scalar() {
3630        let events = Parser::new_from_str("&a !!str value")
3631            .map(|event| event.unwrap().0)
3632            .collect::<Vec<_>>();
3633
3634        let Some(Event::Scalar(value, _, anchor_id, Some(tag))) = events
3635            .iter()
3636            .find(|event| matches!(event, Event::Scalar(value, ..) if value == "value"))
3637        else {
3638            panic!("expected tagged anchored scalar");
3639        };
3640
3641        assert_eq!(value, "value");
3642        assert_eq!(*anchor_id, 1);
3643        assert_eq!(tag.handle, "tag:yaml.org,2002:");
3644        assert_eq!(tag.suffix, "str");
3645        assert_eq!(tag.original_handle, "!!");
3646        assert_eq!(tag.original(), "!!str");
3647    }
3648
3649    #[test]
3650    fn test_tag_then_anchor_applies_both_to_scalar() {
3651        let events = Parser::new_from_str("!!str &a value")
3652            .map(|event| event.unwrap().0)
3653            .collect::<Vec<_>>();
3654
3655        let Some(Event::Scalar(value, _, anchor_id, Some(tag))) = events
3656            .iter()
3657            .find(|event| matches!(event, Event::Scalar(value, ..) if value == "value"))
3658        else {
3659            panic!("expected tagged anchored scalar");
3660        };
3661
3662        assert_eq!(value, "value");
3663        assert_eq!(*anchor_id, 1);
3664        assert_eq!(tag.handle, "tag:yaml.org,2002:");
3665        assert_eq!(tag.suffix, "str");
3666        assert_eq!(tag.original_handle, "!!");
3667        assert_eq!(tag.original(), "!!str");
3668    }
3669
3670    #[test]
3671    fn test_tag_directive_preserves_original_handle() {
3672        let events =
3673            Parser::new_from_str("%TAG !e! tag:example.com,2000:\n---\nconfig: !e!keep value\n")
3674                .map(|event| event.unwrap().0)
3675                .collect::<Vec<_>>();
3676
3677        let (value, tag) = events
3678            .iter()
3679            .find_map(|event| match event {
3680                Event::Scalar(value, _, _, Some(tag)) if value == "value" => Some((value, tag)),
3681                _ => None,
3682            })
3683            .expect("expected tagged scalar");
3684
3685        assert_eq!(value, "value");
3686        assert_eq!(tag.handle, "tag:example.com,2000:");
3687        assert_eq!(tag.suffix, "keep");
3688        assert_eq!(tag.original_handle, "!e!");
3689        assert_eq!(tag.parts(), ("tag:example.com,2000:", "keep"));
3690        assert_eq!(tag.original_parts(), ("!e!", "keep"));
3691        assert_eq!(tag.original(), "!e!keep");
3692    }
3693
3694    #[test]
3695    fn test_verbatim_tag_original_is_normalized_author_spelling() {
3696        let events = Parser::new_from_str("key: !<tag:example.com,2000:thing> value\n")
3697            .map(|event| event.unwrap().0)
3698            .collect::<Vec<_>>();
3699
3700        let Some(Event::Scalar(value, _, _, Some(tag))) = events
3701            .iter()
3702            .find(|event| matches!(event, Event::Scalar(value, ..) if value == "value"))
3703        else {
3704            panic!("expected tagged scalar");
3705        };
3706
3707        assert_eq!(value, "value");
3708        assert_eq!(tag.handle, "");
3709        assert_eq!(tag.suffix, "tag:example.com,2000:thing");
3710        assert_eq!(tag.original_handle, "");
3711        assert_eq!(tag.parts(), ("", "tag:example.com,2000:thing"));
3712        assert_eq!(tag.original_parts(), ("", "tag:example.com,2000:thing"));
3713        assert_eq!(tag.original(), "!<tag:example.com,2000:thing>");
3714    }
3715
3716    #[test]
3717    fn test_multiple_tag_directives_are_kept_within_document() {
3718        let text = r"
3719%TAG !a! tag:a,2024:
3720%TAG !b! tag:b,2024:
3721---
3722first: !a!x foo
3723second: !b!y bar
3724";
3725
3726        let mut seen_a = false;
3727        let mut seen_b = false;
3728        for event in Parser::new_from_str(text) {
3729            let (event, _) = event.unwrap();
3730            if let Event::Scalar(_, _, _, Some(tag)) = event {
3731                if tag.handle == "tag:a,2024:" {
3732                    seen_a = true;
3733                } else if tag.handle == "tag:b,2024:" {
3734                    seen_b = true;
3735                }
3736            }
3737        }
3738
3739        assert!(seen_a);
3740        assert!(seen_b);
3741    }
3742
3743    #[cfg(feature = "error_messages")]
3744    #[test]
3745    fn test_tags_are_cleared_when_next_document_has_no_directives() {
3746        let text = r"
3747%TAG !t! tag:test,2024:
3748--- !t!1
3749foo
3750--- !t!2
3751bar
3752";
3753
3754        let mut parser = Parser::new_from_str(text);
3755        for event in parser.by_ref() {
3756            let (event, _) = event.unwrap();
3757            if let Event::DocumentEnd = event {
3758                break;
3759            }
3760        }
3761
3762        match parser.next().unwrap().unwrap().0 {
3763            Event::DocumentStart(true, None) => {}
3764            _ => panic!("expected explicit second document start"),
3765        }
3766
3767        let err = parser.next().unwrap().unwrap_err();
3768        assert!(format!("{err}").contains("the handle wasn't declared"));
3769    }
3770
3771    #[cfg(feature = "error_messages")]
3772    #[test]
3773    fn test_pull_parser_clears_anchors_between_documents() {
3774        let mut parser = Parser::new_from_str(
3775            "--- &a value
3776--- *a
3777",
3778        );
3779
3780        for event in parser.by_ref() {
3781            let (event, _) = event.unwrap();
3782            if matches!(event, Event::DocumentEnd) {
3783                break;
3784            }
3785        }
3786
3787        match parser.next().unwrap().unwrap().0 {
3788            Event::DocumentStart(true, None) => {}
3789            _ => panic!("expected explicit second document start"),
3790        }
3791
3792        let err = parser.next().unwrap().unwrap_err();
3793        assert!(format!("{err}").contains("unknown anchor"));
3794    }
3795
3796    #[test]
3797    fn test_keep_tags_across_multiple_documents() {
3798        let text = r#"
3799%YAML 1.1
3800%TAG !t! tag:test,2024:
3801--- !t!1 &1
3802foo: "bar"
3803--- !t!2 &2
3804baz: "qux"
3805"#;
3806        for x in Parser::new_from_str(text).keep_tags(true) {
3807            let x = x.unwrap();
3808            if let Event::MappingStart(_, _, tag) = x.0 {
3809                let tag = tag.unwrap();
3810                assert_eq!(tag.handle, "tag:test,2024:");
3811            }
3812        }
3813
3814        for x in Parser::new_from_str(text).keep_tags(false) {
3815            if x.is_err() {
3816                // Test successful
3817                return;
3818            }
3819        }
3820        panic!("Test failed, did not encounter error")
3821    }
3822
3823    #[test]
3824    fn test_flow_sequence_mapping_allows_empty_key() {
3825        let parser = Parser::new_from_str("[?: value]");
3826        for event in parser {
3827            event.expect("parser should accept flow sequence mappings with empty keys");
3828        }
3829    }
3830
3831    #[test]
3832    fn test_keep_tags_does_not_persist_default_tag_handles() {
3833        let text = "%TAG !! tag:evil,2024:\n--- !!int 1\n--- !!int 2\n";
3834
3835        let mut int_tags = Vec::new();
3836        for event in Parser::new_from_str(text).keep_tags(true) {
3837            let event = event.unwrap().0;
3838            if let Event::Scalar(_, _, _, Some(tag)) = event {
3839                if tag.suffix == "int" {
3840                    int_tags.push(tag.handle.clone());
3841                }
3842            }
3843        }
3844
3845        assert_eq!(int_tags, vec!["tag:evil,2024:", "tag:yaml.org,2002:"]);
3846    }
3847
3848    #[test]
3849    fn test_keep_tags_does_not_persist_primary_tag_handle() {
3850        let text = "%TAG ! tag:evil,2024:\n--- !int 1\n--- !int 2\n";
3851
3852        let tags = Parser::new_from_str(text)
3853            .keep_tags(true)
3854            .filter_map(|event| match event.expect("input should parse").0 {
3855                Event::Scalar(_, _, _, Some(tag)) if tag.suffix == "int" => {
3856                    Some(tag.handle.clone())
3857                }
3858                _ => None,
3859            })
3860            .collect::<Vec<_>>();
3861
3862        assert_eq!(tags, vec!["tag:evil,2024:", "!"]);
3863    }
3864
3865    #[test]
3866    fn test_resolve_tag_uses_overridden_local_prefix() {
3867        let mut parser = Parser::new_from_str("");
3868        parser
3869            .tags
3870            .insert("!".into(), "tag:local.example,2024:".into());
3871
3872        let tag = parser
3873            .resolve_tag(
3874                Span::empty(Marker::new(0, 1, 0)),
3875                &Cow::Borrowed(""),
3876                Cow::Borrowed("!"),
3877            )
3878            .unwrap();
3879
3880        assert_eq!(tag.handle, "tag:local.example,2024:");
3881        assert_eq!(tag.suffix, "!");
3882    }
3883
3884    #[test]
3885    fn test_load_after_peek_stream_start() {
3886        #[derive(Default)]
3887        struct Sink<'input> {
3888            events: Vec<Event<'input>>,
3889        }
3890
3891        impl<'input> EventReceiver<'input> for Sink<'input> {
3892            fn on_event(&mut self, ev: Event<'input>) {
3893                self.events.push(ev);
3894            }
3895        }
3896
3897        let mut parser = Parser::new_from_str("key: value\n");
3898        let mut sink = Sink::default();
3899
3900        assert_eq!(parser.peek().unwrap().unwrap().0, Event::StreamStart);
3901        parser.load(&mut sink, false).unwrap();
3902
3903        assert!(matches!(sink.events.first(), Some(Event::StreamStart)));
3904        assert!(matches!(sink.events.get(1), Some(Event::DocumentStart(..))));
3905    }
3906}