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