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            // "!" introduces a local tag. Local tags may have their prefix overridden.
2496            match self.tags.get("!") {
2497                Some(prefix) => {
2498                    Tag::with_original_handle(prefix.to_string(), suffix, original_handle)
2499                }
2500                None => Tag::with_original_handle(String::new(), suffix, original_handle),
2501            }
2502        } else {
2503            // Lookup handle in our tag directives.
2504            let prefix = self.tags.get(&**handle);
2505            if let Some(prefix) = prefix {
2506                Tag::with_original_handle(prefix.to_string(), suffix, original_handle)
2507            } else {
2508                // Otherwise, it may be a local handle. With a local handle, the handle is set to
2509                // "!" and the suffix to whatever follows it ("!foo" -> ("!", "foo")).
2510                // If the handle is of the form "!foo!", this cannot be a local handle and we need
2511                // to error.
2512                if handle.len() >= 2 && handle.starts_with('!') && handle.ends_with('!') {
2513                    return Err(ScanError::from_kind(
2514                        span.start,
2515                        ErrorKind::UndeclaredTagHandle,
2516                    ));
2517                }
2518                Tag::with_original_handle(handle.to_string(), suffix, original_handle)
2519            }
2520        };
2521        Ok(Cow::Owned(tag))
2522    }
2523}
2524
2525impl<'input, T: BorrowedInput<'input>> ParserTrait<'input> for Parser<'input, T> {
2526    fn peek(&mut self) -> Option<Result<&(Event<'input>, Span), ScanError>> {
2527        if let Some(ref x) = self.current {
2528            Some(Ok(x))
2529        } else if let Some(error) = &self.current_error {
2530            Some(Err(error.clone()))
2531        } else {
2532            if self.stream_end_emitted {
2533                return None;
2534            }
2535            match self.next_event_impl() {
2536                Ok(token) => self.current = Some(token),
2537                Err(error) => {
2538                    self.current_error = Some(error.clone());
2539                    return Some(Err(error));
2540                }
2541            }
2542            self.current.as_ref().map(Ok)
2543        }
2544    }
2545
2546    fn next_event(&mut self) -> Option<ParseResult<'input>> {
2547        if let Some(error) = self.current_error.take() {
2548            self.stream_end_emitted = true;
2549            return Some(Err(error));
2550        }
2551
2552        if self.stream_end_emitted {
2553            return None;
2554        }
2555
2556        let tok = self.next_event_impl();
2557        if matches!(tok, Ok((Event::StreamEnd, _)) | Err(_)) {
2558            self.stream_end_emitted = true;
2559        }
2560        Some(tok)
2561    }
2562
2563    fn load<R: SpannedEventReceiver<'input>>(
2564        &mut self,
2565        recv: &mut R,
2566        multi: bool,
2567    ) -> Result<(), ScanError> {
2568        let mut recv = InfallibleSpannedReceiver(recv);
2569        into_scan_result(ParserTrait::try_load(self, &mut recv, multi))
2570    }
2571
2572    fn try_load<R: TrySpannedEventReceiver<'input>>(
2573        &mut self,
2574        recv: &mut R,
2575        multi: bool,
2576    ) -> Result<(), TryLoadError<R::Error>> {
2577        let stream_start_buffered = matches!(self.current.as_ref(), Some((Event::StreamStart, _)));
2578        if !self.scanner.stream_started() || stream_start_buffered {
2579            let (ev, span) = self.next_event_impl()?;
2580            if ev != Event::StreamStart {
2581                return Err(TryLoadError::scan(ScanError::from_kind(
2582                    span.start,
2583                    ErrorKind::ExpectedStreamStart,
2584                )));
2585            }
2586            try_emit(recv, ev, span)?;
2587        }
2588
2589        let has_buffered_result = self.current.is_some()
2590            || self.current_error.is_some()
2591            || self.deferred_error.is_some()
2592            || !self.queued_events.is_empty();
2593        if self.scanner.stream_ended() && !has_buffered_result {
2594            // The scanner has already reached EOF before the document loop, so emit the terminal
2595            // event and stop.
2596            try_emit(recv, Event::StreamEnd, Span::empty(self.scanner.mark()))?;
2597            self.stream_end_emitted = true;
2598            return Ok(());
2599        }
2600
2601        loop {
2602            let (ev, span) = if let Some(error) = self.current_error.take() {
2603                self.stream_end_emitted = true;
2604                return Err(TryLoadError::scan(error));
2605            } else {
2606                self.next_event_impl()?
2607            };
2608            let is_doc_end = matches!(ev, Event::DocumentEnd);
2609            let is_stream_end = matches!(ev, Event::StreamEnd);
2610
2611            try_emit(recv, ev, span)?;
2612
2613            if is_stream_end {
2614                self.stream_end_emitted = true;
2615                return Ok(());
2616            }
2617            if !multi && is_doc_end {
2618                return Ok(());
2619            }
2620        }
2621    }
2622}
2623
2624impl<'input, T: BorrowedInput<'input>> Iterator for Parser<'input, T> {
2625    type Item = Result<(Event<'input>, Span), ScanError>;
2626
2627    fn next(&mut self) -> Option<Self::Item> {
2628        self.next_event()
2629    }
2630}
2631
2632impl<'input, T: BorrowedInput<'input>> core::iter::FusedIterator for Parser<'input, T> {}
2633
2634#[cfg(test)]
2635mod test {
2636    use alloc::{borrow::Cow, string::ToString, vec, vec::Vec};
2637    #[cfg(feature = "error_messages")]
2638    use alloc::{format, string::String};
2639    #[cfg(feature = "error_messages")]
2640    use core::{error::Error as _, fmt};
2641
2642    #[cfg(feature = "error_messages")]
2643    use crate::error::{ErrorKind, ScanError};
2644    use crate::scanner::{Marker, ScalarStyle, Span};
2645
2646    use super::{
2647        Event, EventReceiver, Parser, State, StructureStyle, Tag, TryEventReceiver, TryLoadError,
2648        TrySpannedEventReceiver, YamlVersion,
2649    };
2650
2651    #[derive(Default)]
2652    struct CollectingSink<'input> {
2653        events: Vec<Event<'input>>,
2654    }
2655
2656    impl<'input> EventReceiver<'input> for CollectingSink<'input> {
2657        fn on_event(&mut self, ev: Event<'input>) {
2658            self.events.push(ev);
2659        }
2660    }
2661
2662    #[cfg(feature = "error_messages")]
2663    fn first_error_info(input: &str) -> String {
2664        for event in Parser::new_from_str(input) {
2665            if let Err(err) = event {
2666                return err.info();
2667            }
2668        }
2669        panic!("expected parser error")
2670    }
2671
2672    fn first_tagged_scalar_tag(input: &str) -> Tag {
2673        Parser::new_from_str(input)
2674            .find_map(|event| match event.expect("input should parse").0 {
2675                Event::Scalar(_, _, _, Some(tag)) => Some(tag.into_owned()),
2676                _ => None,
2677            })
2678            .expect("expected tagged scalar")
2679    }
2680
2681    #[test]
2682    fn deferred_parse_node_can_emit_comment_before_flow_node() {
2683        let mut parser = Parser::new_from_str("---\n# deferred\nvalue\n");
2684        assert_eq!(parser.stream_start().unwrap().0, Event::StreamStart);
2685        assert_eq!(
2686            parser.document_start(true).unwrap().0,
2687            Event::DocumentStart(true, None)
2688        );
2689
2690        let (event, _) = parser
2691            .defer_parse_node(State::FlowNode, State::FlowMappingKey, false, false)
2692            .unwrap();
2693
2694        assert!(matches!(event, Event::Comment(text, _) if text == " deferred"));
2695        assert_eq!(parser.state, State::FlowNode);
2696    }
2697
2698    #[test]
2699    fn queued_node_event_gets_pending_key_indent() {
2700        let mut parser = Parser::new_from_str("");
2701        let span = Span::empty(Marker::new(0, 1, 0));
2702
2703        parser.pending_key_indent = Some(3);
2704        parser
2705            .queued_events
2706            .push_back((Event::SequenceStart(StructureStyle::Block, 0, None), span));
2707
2708        let (event, span) = parser.next_event_impl().unwrap();
2709
2710        assert!(matches!(
2711            event,
2712            Event::SequenceStart(StructureStyle::Block, 0, None)
2713        ));
2714        assert_eq!(span.indent, Some(3));
2715        assert_eq!(parser.pending_key_indent, None);
2716    }
2717
2718    #[test]
2719    fn state_machine_handles_deferred_flow_node_states() {
2720        let mut parser = Parser::new_from_str("value\n");
2721        assert_eq!(parser.stream_start().unwrap().0, Event::StreamStart);
2722        assert_eq!(
2723            parser.document_start(true).unwrap().0,
2724            Event::DocumentStart(false, None)
2725        );
2726        parser.state = State::FlowNode;
2727        parser.push_state(State::End);
2728
2729        let (event, _) = parser.state_machine().unwrap();
2730
2731        assert!(matches!(event, Event::Scalar(value, ..) if value == "value"));
2732
2733        let mut parser = Parser::new_from_str("value\n");
2734        assert_eq!(parser.stream_start().unwrap().0, Event::StreamStart);
2735        assert_eq!(
2736            parser.document_start(true).unwrap().0,
2737            Event::DocumentStart(false, None)
2738        );
2739        parser.state = State::FlowSequenceEntryMappingValueNode;
2740
2741        let (event, _) = parser.state_machine().unwrap();
2742
2743        assert!(matches!(event, Event::Scalar(value, ..) if value == "value"));
2744    }
2745
2746    #[test]
2747    fn display_resolved_core_tag_without_extra_bang() {
2748        let tag = Tag::with_original_handle("tag:yaml.org,2002:", "str", "!!");
2749
2750        assert_eq!(tag.to_string(), "tag:yaml.org,2002:str");
2751    }
2752
2753    #[test]
2754    fn tag_helpers_distinguish_core_and_local_tags() {
2755        let core = Tag::with_original_handle("tag:yaml.org,2002:", "int", "!!");
2756        let local = Tag::new("!", "thing");
2757        let non_specific = Tag::with_original_handle("", "!", "");
2758        let verbatim = Tag::with_original_handle("", "tag:example.com,2000:thing", "");
2759        let unknown_yaml_org = Tag::with_original_handle("", "tag:yaml.org,2002:application", "");
2760
2761        assert_eq!(core.core_suffix(), Some("int"));
2762        assert!(core.is_yaml_core_schema());
2763        assert!(core.is_yaml_core_schema_tag("int"));
2764        assert!(!core.is_yaml_core_schema_tag("str"));
2765        assert!(!core.is_custom());
2766        assert_eq!(core.parts(), ("tag:yaml.org,2002:", "int"));
2767        assert_eq!(core.original_parts(), ("!!", "int"));
2768        assert_eq!(core.original(), "!!int");
2769
2770        assert_eq!(local.core_suffix(), None);
2771        assert!(!local.is_yaml_core_schema());
2772        assert!(!local.is_yaml_core_schema_tag("thing"));
2773        assert!(local.is_custom());
2774        assert_eq!(local.parts(), ("!", "thing"));
2775        assert_eq!(local.original_parts(), ("!", "thing"));
2776        assert_eq!(local.original(), "!thing");
2777        assert_eq!(local.to_string(), "!thing");
2778
2779        assert_eq!(non_specific.parts(), ("", "!"));
2780        assert_eq!(non_specific.original_parts(), ("", "!"));
2781        assert_eq!(non_specific.original(), "!");
2782
2783        assert_eq!(verbatim.parts(), ("", "tag:example.com,2000:thing"));
2784        assert_eq!(
2785            verbatim.original_parts(),
2786            ("", "tag:example.com,2000:thing")
2787        );
2788        assert_eq!(verbatim.original(), "!<tag:example.com,2000:thing>");
2789
2790        assert_eq!(unknown_yaml_org.core_suffix(), None);
2791        assert!(!unknown_yaml_org.is_yaml_core_schema());
2792        assert!(unknown_yaml_org.is_custom());
2793    }
2794
2795    #[test]
2796    fn core_suffix_uses_resolved_tag_uri_for_common_spellings() {
2797        let cases = [
2798            ("shorthand", "v: !!int 1\n", ("tag:yaml.org,2002:", "int")),
2799            (
2800                "verbatim",
2801                "v: !<tag:yaml.org,2002:int> 1\n",
2802                ("", "tag:yaml.org,2002:int"),
2803            ),
2804            (
2805                "full prefix",
2806                "%TAG !e! tag:yaml.org,2002:\n---\nv: !e!int 1\n",
2807                ("tag:yaml.org,2002:", "int"),
2808            ),
2809            (
2810                "mid-split",
2811                "%TAG !m! tag:yaml.org,2002:i\n---\nv: !m!nt 1\n",
2812                ("tag:yaml.org,2002:i", "nt"),
2813            ),
2814        ];
2815
2816        for (label, input, expected_parts) in cases {
2817            let tag = first_tagged_scalar_tag(input);
2818
2819            assert_eq!(tag.parts(), expected_parts, "{label}");
2820            assert_eq!(tag.core_suffix(), Some("int"), "{label}");
2821            assert!(tag.is_yaml_core_schema(), "{label}");
2822            assert!(tag.is_yaml_core_schema_tag("int"), "{label}");
2823            assert!(!tag.is_yaml_core_schema_tag("str"), "{label}");
2824            assert!(!tag.is_custom(), "{label}");
2825        }
2826    }
2827
2828    #[test]
2829    fn core_suffix_rejects_non_core_yaml_org_tags() {
2830        let cases = [
2831            "binary",
2832            "merge",
2833            "omap",
2834            "pairs",
2835            "set",
2836            "timestamp",
2837            "value",
2838            "yaml",
2839        ];
2840
2841        for suffix in cases {
2842            let tag = Tag::with_original_handle("tag:yaml.org,2002:", suffix, "!!");
2843
2844            assert_eq!(tag.core_suffix(), None, "{suffix}");
2845            assert!(!tag.is_yaml_core_schema(), "{suffix}");
2846            assert!(tag.is_custom(), "{suffix}");
2847        }
2848    }
2849
2850    #[test]
2851    fn core_suffix_rejects_non_core_tags() {
2852        let cases = [
2853            ("local", "v: !local 1\n"),
2854            ("verbatim custom", "v: !<tag:example.com,2000:int> 1\n"),
2855            (
2856                "custom directive",
2857                "%TAG !e! tag:example.com,2000:\n---\nv: !e!int 1\n",
2858            ),
2859            (
2860                "overridden secondary handle",
2861                "%TAG !! tag:example.com,2000:app/\n---\nv: !!int 1\n",
2862            ),
2863        ];
2864
2865        for (label, input) in cases {
2866            let tag = first_tagged_scalar_tag(input);
2867
2868            assert_eq!(tag.core_suffix(), None, "{label}");
2869            assert!(!tag.is_yaml_core_schema(), "{label}");
2870            assert!(!tag.is_yaml_core_schema_tag("int"), "{label}");
2871            assert!(tag.is_custom(), "{label}");
2872        }
2873    }
2874
2875    #[test]
2876    fn suffix_in_namespace_resolves_across_spellings() {
2877        const NS: &str = "tag:yaml.org,2002:";
2878
2879        // Every spelling of `tag:yaml.org,2002:omap` resolves to the same name, even though
2880        // `omap` is not a Core Schema type (so `core_suffix` reports `None`). `mid_split` cuts
2881        // the URI after the namespace prefix (handle longer than `NS`); `inside_split` cuts it
2882        // before the prefix ends (handle a non-empty prefix of `NS`), exercising both branches.
2883        let shorthand = Tag::with_original_handle(NS, "omap", "!!");
2884        let verbatim = Tag::with_original_handle("", "tag:yaml.org,2002:omap", "");
2885        let mid_split = Tag::with_original_handle("tag:yaml.org,2002:o", "map", "!o!");
2886        let inside_split = Tag::with_original_handle("tag:yaml.org,", "2002:omap", "!y!");
2887        for tag in [&shorthand, &verbatim, &mid_split, &inside_split] {
2888            assert_eq!(tag.suffix_in_namespace(NS).as_deref(), Some("omap"));
2889            assert_eq!(tag.core_suffix(), None);
2890        }
2891
2892        // Borrow whenever the resolved name is a contiguous slice of `handle` or `suffix`;
2893        // allocate only when a split lands inside the name itself (handle extends past `NS`).
2894        assert!(matches!(
2895            shorthand.suffix_in_namespace(NS),
2896            Some(Cow::Borrowed(_))
2897        ));
2898        assert!(matches!(
2899            verbatim.suffix_in_namespace(NS),
2900            Some(Cow::Borrowed(_))
2901        ));
2902        assert!(matches!(
2903            inside_split.suffix_in_namespace(NS),
2904            Some(Cow::Borrowed(_))
2905        ));
2906        assert!(matches!(
2907            mid_split.suffix_in_namespace(NS),
2908            Some(Cow::Owned(_))
2909        ));
2910
2911        // The non-core `merge` type resolves the same way; core types still flow through
2912        // `core_suffix`.
2913        let merge = Tag::with_original_handle(NS, "merge", "!!");
2914        assert_eq!(merge.suffix_in_namespace(NS).as_deref(), Some("merge"));
2915        assert_eq!(merge.core_suffix(), None);
2916        assert_eq!(
2917            Tag::new(NS, "int").suffix_in_namespace(NS).as_deref(),
2918            Some("int")
2919        );
2920
2921        // Tags outside the namespace do not resolve into it.
2922        assert_eq!(Tag::new("!", "omap").suffix_in_namespace(NS), None);
2923        assert_eq!(
2924            Tag::with_original_handle("", "tag:example.com,2000:omap", "").suffix_in_namespace(NS),
2925            None
2926        );
2927    }
2928
2929    #[test]
2930    fn attach_tag_start_applies_marker_to_span() {
2931        let event = Event::Scalar("value".into(), ScalarStyle::Plain, 0, None);
2932        let span = Span::new(Marker::new(6, 1, 6), Marker::new(11, 1, 11));
2933        let tag_start = Marker::new(0, 1, 0);
2934
2935        let (attached_event, attached_span) =
2936            Parser::<crate::input::str::StrInput<'_>>::attach_tag_start(
2937                event.clone(),
2938                span,
2939                Some(tag_start),
2940            );
2941
2942        assert_eq!(attached_event, event);
2943        assert_eq!(attached_span.start, span.start);
2944        assert_eq!(attached_span.end, span.end);
2945        assert_eq!(attached_span.tag_start(), Some(tag_start));
2946    }
2947
2948    #[test]
2949    fn event_inspection_helpers_report_node_metadata() {
2950        let tag = Tag::new("!", "thing");
2951        let scalar = Event::Scalar(
2952            "value".into(),
2953            ScalarStyle::DoubleQuoted,
2954            7,
2955            Some(Cow::Borrowed(&tag)),
2956        );
2957        let sequence =
2958            Event::SequenceStart(StructureStyle::Block, 8, Some(Cow::Owned(tag.clone())));
2959        let mapping = Event::MappingStart(StructureStyle::Block, 9, Some(Cow::Borrowed(&tag)));
2960
2961        assert_eq!(scalar.anchor_id(), Some(7));
2962        assert_eq!(scalar.alias_id(), None);
2963        assert_eq!(scalar.tag(), Some(&tag));
2964        assert_eq!(scalar.scalar(), Some(("value", ScalarStyle::DoubleQuoted)));
2965        assert!(scalar.is_node());
2966
2967        assert_eq!(sequence.anchor_id(), Some(8));
2968        assert_eq!(sequence.alias_id(), None);
2969        assert_eq!(sequence.tag(), Some(&tag));
2970        assert_eq!(sequence.scalar(), None);
2971        assert!(sequence.is_node());
2972
2973        assert_eq!(mapping.anchor_id(), Some(9));
2974        assert_eq!(mapping.alias_id(), None);
2975        assert_eq!(mapping.tag(), Some(&tag));
2976        assert_eq!(mapping.scalar(), None);
2977        assert!(mapping.is_node());
2978
2979        let alias = Event::Alias(10);
2980        assert_eq!(alias.anchor_id(), None);
2981        assert_eq!(alias.alias_id(), Some(10));
2982        assert_eq!(alias.tag(), None);
2983        assert_eq!(alias.scalar(), None);
2984        assert!(alias.is_node());
2985
2986        let unanchored_scalar = Event::Scalar("x".into(), ScalarStyle::Plain, 0, None);
2987        assert_eq!(unanchored_scalar.anchor_id(), None);
2988        assert_eq!(unanchored_scalar.alias_id(), None);
2989
2990        let stream_start = Event::StreamStart;
2991        assert_eq!(stream_start.anchor_id(), None);
2992        assert_eq!(stream_start.alias_id(), None);
2993        assert_eq!(stream_start.tag(), None);
2994        assert_eq!(stream_start.scalar(), None);
2995        assert!(!stream_start.is_node());
2996    }
2997
2998    #[test]
2999    fn test_peek_eq_parse() {
3000        let s = "
3001a0 bb: val
3002a1: &x
3003    b1: 4
3004    b2: d
3005a2: 4
3006a3: [1, 2, 3]
3007a4:
3008    - [a1, a2]
3009    - 2
3010a5: *x
3011";
3012        let mut p = Parser::new_from_str(s);
3013        loop {
3014            let event_peek = p.peek().unwrap().unwrap().clone();
3015            let event = p.next_event().unwrap().unwrap();
3016            assert_eq!(event, event_peek);
3017            if event.0 == Event::StreamEnd {
3018                break;
3019            }
3020        }
3021    }
3022
3023    #[test]
3024    fn test_repeated_peek_returns_buffered_event() {
3025        let mut parser = Parser::new_from_str("key: value\n");
3026
3027        let first_peek = parser.peek().unwrap().unwrap().clone();
3028        let second_peek = parser.peek().unwrap().unwrap().clone();
3029        let next = parser.next_event().unwrap().unwrap();
3030
3031        assert_eq!(first_peek, second_peek);
3032        assert_eq!(first_peek, next);
3033    }
3034
3035    #[cfg(feature = "error_messages")]
3036    #[test]
3037    fn test_peek_surfaces_scan_error_without_consuming_stream_end_state() {
3038        let mut parser = Parser::new_from_str("a: [1, 2");
3039
3040        loop {
3041            match parser.peek() {
3042                Some(Ok(_)) => {
3043                    parser.next_event().unwrap().unwrap();
3044                }
3045                Some(Err(error)) => {
3046                    assert_eq!(error.info(), "unclosed bracket '['");
3047                    break;
3048                }
3049                None => panic!("expected parse error"),
3050            }
3051        }
3052    }
3053
3054    #[test]
3055    fn test_iterator_terminates_after_scan_error() {
3056        let parser = Parser::new_from_str("foo:\n  bar\ninvalid\n");
3057        let mut errors = 0usize;
3058        let mut events = 0usize;
3059
3060        for item in parser {
3061            events += 1;
3062            if item.is_err() {
3063                errors += 1;
3064            }
3065            assert!(
3066                events < 1000,
3067                "parser iterator did not terminate after a scan error"
3068            );
3069        }
3070
3071        assert_eq!(errors, 1);
3072    }
3073
3074    #[cfg(feature = "error_messages")]
3075    #[test]
3076    fn test_iterator_terminates_after_node_property_error() {
3077        let parser = Parser::new_from_str("- *nope\n- 2\n");
3078        let mut errors = 0usize;
3079        let mut saw_later_node = false;
3080        let mut events = 0usize;
3081
3082        for item in parser {
3083            events += 1;
3084            match item {
3085                Ok((Event::Scalar(value, ..), _)) if value == "2" => saw_later_node = true,
3086                Ok(_) => {}
3087                Err(error) => {
3088                    assert_eq!(error.info(), "while parsing node, found unknown anchor");
3089                    errors += 1;
3090                }
3091            }
3092            assert!(
3093                events < 1000,
3094                "parser iterator did not terminate after a node-property error"
3095            );
3096        }
3097
3098        assert_eq!(errors, 1);
3099        assert!(!saw_later_node, "parser resumed after the alias error");
3100    }
3101
3102    #[test]
3103    fn test_peeked_scan_error_is_returned_once_by_next_event() {
3104        let mut parser = Parser::new_from_str("a: [1, 2");
3105
3106        let first_error = loop {
3107            match parser.peek() {
3108                Some(Ok(_)) => {
3109                    parser.next_event().unwrap().unwrap();
3110                }
3111                Some(Err(error)) => break error,
3112                None => panic!("expected parse error"),
3113            }
3114        };
3115        let Some(Err(second_error)) = parser.peek() else {
3116            panic!("expected cached parse error");
3117        };
3118
3119        assert_eq!(first_error, second_error);
3120        assert_eq!(parser.next_event().unwrap().unwrap_err(), first_error);
3121        assert!(parser.next_event().is_none());
3122        assert!(parser.peek().is_none());
3123    }
3124
3125    #[cfg(feature = "error_messages")]
3126    #[test]
3127    fn test_peeked_node_property_error_is_stable_and_terminal() {
3128        let mut parser = Parser::new_from_str("a: *nope\nb: 2\n");
3129
3130        for _ in 0..4 {
3131            parser.next_event().unwrap().unwrap();
3132        }
3133
3134        let Some(Err(first_error)) = parser.peek() else {
3135            panic!("expected unknown alias error");
3136        };
3137        let Some(Err(second_error)) = parser.peek() else {
3138            panic!("expected cached unknown alias error");
3139        };
3140
3141        assert_eq!(first_error, second_error);
3142        assert_eq!(
3143            first_error.info(),
3144            "while parsing node, found unknown anchor"
3145        );
3146        assert_eq!(parser.next_event().unwrap().unwrap_err(), first_error);
3147        assert!(parser.next_event().is_none());
3148        assert!(parser.peek().is_none());
3149    }
3150
3151    #[test]
3152    fn test_peek_and_next_return_none_after_stream_end() {
3153        let mut parser = Parser::new_from_str("");
3154
3155        assert!(matches!(
3156            parser.next_event().unwrap().unwrap().0,
3157            Event::StreamStart
3158        ));
3159        assert!(matches!(
3160            parser.next_event().unwrap().unwrap().0,
3161            Event::StreamEnd
3162        ));
3163        assert!(parser.next_event().is_none());
3164        assert!(parser.peek().is_none());
3165    }
3166
3167    #[test]
3168    fn test_load_after_stream_already_ended_emits_stream_end() {
3169        let mut parser = Parser::new_from_str("");
3170        while parser.next_event().is_some() {}
3171
3172        let mut sink = CollectingSink::default();
3173        parser.load(&mut sink, true).unwrap();
3174
3175        assert_eq!(sink.events, vec![Event::StreamEnd]);
3176    }
3177
3178    #[test]
3179    fn test_load_full_stream_fuses_iterator_after_stream_end() {
3180        let mut parser = Parser::new_from_str("a: 1\n");
3181        let mut sink = CollectingSink::default();
3182
3183        parser.load(&mut sink, true).unwrap();
3184
3185        assert!(matches!(sink.events.last(), Some(Event::StreamEnd)));
3186        assert!(parser.next_event().is_none());
3187        assert!(parser.peek().is_none());
3188    }
3189
3190    #[test]
3191    fn test_load_after_peek_delivers_buffered_document_end_before_stream_end() {
3192        let mut parser = Parser::new_from_str("a");
3193        for _ in 0..3 {
3194            parser.next_event().unwrap().unwrap();
3195        }
3196
3197        assert_eq!(parser.peek().unwrap().unwrap().0, Event::DocumentEnd);
3198
3199        let mut sink = CollectingSink::default();
3200        parser.load(&mut sink, true).unwrap();
3201
3202        assert_eq!(sink.events, vec![Event::DocumentEnd, Event::StreamEnd]);
3203        assert!(parser.next_event().is_none());
3204    }
3205
3206    #[test]
3207    fn test_load_visits_nested_collection_events() {
3208        let mut parser = Parser::new_from_str("root:\n  - item: value\n  - [a, b]\n");
3209        let mut sink = CollectingSink::default();
3210
3211        parser.load(&mut sink, true).unwrap();
3212
3213        assert_eq!(
3214            sink.events,
3215            vec![
3216                Event::StreamStart,
3217                Event::DocumentStart(false, None),
3218                Event::MappingStart(StructureStyle::Block, 0, None),
3219                Event::Scalar("root".into(), ScalarStyle::Plain, 0, None),
3220                Event::SequenceStart(StructureStyle::Block, 0, None),
3221                Event::MappingStart(StructureStyle::Block, 0, None),
3222                Event::Scalar("item".into(), ScalarStyle::Plain, 0, None),
3223                Event::Scalar("value".into(), ScalarStyle::Plain, 0, None),
3224                Event::MappingEnd,
3225                Event::SequenceStart(StructureStyle::Flow, 0, None),
3226                Event::Scalar("a".into(), ScalarStyle::Plain, 0, None),
3227                Event::Scalar("b".into(), ScalarStyle::Plain, 0, None),
3228                Event::SequenceEnd,
3229                Event::SequenceEnd,
3230                Event::MappingEnd,
3231                Event::DocumentEnd,
3232                Event::StreamEnd,
3233            ]
3234        );
3235    }
3236
3237    #[derive(Clone, Debug, PartialEq, Eq)]
3238    enum ValidationError {
3239        ForbiddenValue,
3240    }
3241
3242    #[cfg(feature = "error_messages")]
3243    #[derive(Debug)]
3244    struct ReceiverFailure;
3245
3246    #[cfg(feature = "error_messages")]
3247    impl fmt::Display for ReceiverFailure {
3248        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3249            write!(f, "receiver failed")
3250        }
3251    }
3252
3253    #[cfg(feature = "error_messages")]
3254    impl core::error::Error for ReceiverFailure {}
3255
3256    struct FailingSink<'input> {
3257        events: Vec<Event<'input>>,
3258    }
3259
3260    impl<'input> TryEventReceiver<'input> for FailingSink<'input> {
3261        type Error = ValidationError;
3262
3263        fn on_event(&mut self, ev: Event<'input>) -> Result<(), Self::Error> {
3264            let should_fail = matches!(&ev, Event::Scalar(value, ..) if value.as_ref() == "bad");
3265            self.events.push(ev);
3266            if should_fail {
3267                Err(ValidationError::ForbiddenValue)
3268            } else {
3269                Ok(())
3270            }
3271        }
3272    }
3273
3274    #[test]
3275    fn test_try_load_stops_on_receiver_error() {
3276        let mut parser = Parser::new_from_str("ok: bad\nafter: value\n");
3277        let mut sink = FailingSink { events: Vec::new() };
3278
3279        let err = parser.try_load(&mut sink, true).unwrap_err();
3280
3281        assert_eq!(err, TryLoadError::Receiver(ValidationError::ForbiddenValue));
3282        assert!(sink
3283            .events
3284            .iter()
3285            .any(|event| matches!(event, Event::Scalar(value, ..) if value == "ok")));
3286        assert!(sink
3287            .events
3288            .iter()
3289            .any(|event| matches!(event, Event::Scalar(value, ..) if value == "bad")));
3290        assert!(!sink
3291            .events
3292            .iter()
3293            .any(|event| matches!(event, Event::Scalar(value, ..) if value == "after")));
3294    }
3295
3296    struct SpannedFailingSink {
3297        failed_span: Option<Span>,
3298    }
3299
3300    impl<'input> TrySpannedEventReceiver<'input> for SpannedFailingSink {
3301        type Error = Span;
3302
3303        fn on_event(&mut self, ev: Event<'input>, span: Span) -> Result<(), Self::Error> {
3304            if matches!(ev, Event::Scalar(value, ..) if value.as_ref() == "bad") {
3305                self.failed_span = Some(span);
3306                Err(span)
3307            } else {
3308                Ok(())
3309            }
3310        }
3311    }
3312
3313    #[test]
3314    fn test_try_load_spanned_receiver_gets_span() {
3315        let mut parser = Parser::new_from_str("value: bad\n");
3316        let mut sink = SpannedFailingSink { failed_span: None };
3317
3318        let err = parser.try_load(&mut sink, false).unwrap_err();
3319
3320        let TryLoadError::Receiver(span) = err else {
3321            panic!("expected receiver error");
3322        };
3323
3324        assert_eq!(Some(span), sink.failed_span);
3325        assert!(!span.is_empty());
3326    }
3327
3328    #[cfg(feature = "error_messages")]
3329    struct NeverFails {
3330        count: usize,
3331    }
3332
3333    #[cfg(feature = "error_messages")]
3334    impl<'input> TryEventReceiver<'input> for NeverFails {
3335        type Error = ValidationError;
3336
3337        fn on_event(&mut self, _ev: Event<'input>) -> Result<(), Self::Error> {
3338            self.count += 1;
3339            Ok(())
3340        }
3341    }
3342
3343    #[cfg(feature = "error_messages")]
3344    #[test]
3345    fn test_try_load_returns_scan_error() {
3346        let mut parser = Parser::new_from_str("%YAML 1.2\n%YAML 1.2\n---\n");
3347        let mut sink = NeverFails { count: 0 };
3348
3349        let err = parser.try_load(&mut sink, true).unwrap_err();
3350
3351        let TryLoadError::Scan(err) = err else {
3352            panic!("expected scan error");
3353        };
3354        assert_eq!(err.kind(), &ErrorKind::DuplicateVersionDirective);
3355        assert_eq!(err.info(), "duplicate version directive");
3356    }
3357
3358    #[cfg(feature = "error_messages")]
3359    #[test]
3360    fn test_try_load_error_display_and_source_cover_both_variants() {
3361        let scan = ScanError::from_kind(Marker::new(3, 1, 3), ErrorKind::UnexpectedEof);
3362        let scan_err: TryLoadError<ReceiverFailure> = scan.into();
3363
3364        assert!(scan_err
3365            .to_string()
3366            .starts_with("parser error: unexpected eof"));
3367        assert!(scan_err.source().is_some());
3368
3369        let receiver_err = TryLoadError::Receiver(ReceiverFailure);
3370
3371        assert_eq!(receiver_err.to_string(), "receiver error: receiver failed");
3372        assert!(receiver_err.source().is_some());
3373    }
3374
3375    #[cfg(feature = "error_messages")]
3376    #[test]
3377    fn test_try_load_requires_buffered_stream_start() {
3378        let mut parser = Parser::new_from_str("");
3379        let span = Span::empty(Marker::new(0, 1, 0));
3380        parser.current = Some((
3381            Event::Scalar("value".into(), ScalarStyle::Plain, 0, None),
3382            span,
3383        ));
3384        let mut sink = NeverFails { count: 0 };
3385
3386        let err = parser.try_load(&mut sink, true).unwrap_err();
3387
3388        let TryLoadError::Scan(err) = err else {
3389            panic!("expected scan error");
3390        };
3391        assert_eq!(err.info(), "did not find expected <stream-start>");
3392    }
3393
3394    #[test]
3395    fn test_try_load_after_stream_already_ended_emits_stream_end() {
3396        let mut parser = Parser::new_from_str("");
3397        while parser.next_event().is_some() {}
3398
3399        let mut sink = FailingSink { events: Vec::new() };
3400        parser.try_load(&mut sink, true).unwrap();
3401
3402        assert_eq!(sink.events, vec![Event::StreamEnd]);
3403    }
3404
3405    #[test]
3406    fn test_try_load_full_stream_fuses_iterator_after_stream_end() {
3407        let mut parser = Parser::new_from_str("a: 1\n");
3408        let mut sink = FailingSink { events: Vec::new() };
3409
3410        parser.try_load(&mut sink, true).unwrap();
3411
3412        assert!(matches!(sink.events.last(), Some(Event::StreamEnd)));
3413        assert!(parser.next_event().is_none());
3414        assert!(parser.peek().is_none());
3415    }
3416
3417    #[test]
3418    fn test_try_load_after_peek_delivers_buffered_document_end_before_stream_end() {
3419        let mut parser = Parser::new_from_str("a");
3420        for _ in 0..3 {
3421            parser.next_event().unwrap().unwrap();
3422        }
3423
3424        assert_eq!(parser.peek().unwrap().unwrap().0, Event::DocumentEnd);
3425
3426        let mut sink = FailingSink { events: Vec::new() };
3427        parser.try_load(&mut sink, true).unwrap();
3428
3429        assert_eq!(sink.events, vec![Event::DocumentEnd, Event::StreamEnd]);
3430        assert!(parser.next_event().is_none());
3431    }
3432
3433    #[test]
3434    fn test_load_single_document_stops_before_next_document() {
3435        let mut parser = Parser::new_from_str("a: 1\n---\nb: 2\n");
3436        let mut sink = CollectingSink::default();
3437
3438        parser.load(&mut sink, false).unwrap();
3439
3440        assert!(sink
3441            .events
3442            .iter()
3443            .any(|event| matches!(event, Event::Scalar(value, ..) if value == "a")));
3444        assert!(!sink
3445            .events
3446            .iter()
3447            .any(|event| matches!(event, Event::Scalar(value, ..) if value == "b")));
3448        assert!(matches!(sink.events.last(), Some(Event::DocumentEnd)));
3449    }
3450
3451    #[cfg(feature = "error_messages")]
3452    #[test]
3453    fn test_duplicate_version_directive_errors() {
3454        assert_eq!(
3455            first_error_info("%YAML 1.2\n%YAML 1.2\n---\n"),
3456            "duplicate version directive"
3457        );
3458    }
3459
3460    #[cfg(feature = "error_messages")]
3461    #[test]
3462    fn test_unsupported_yaml_major_version_errors() {
3463        assert_eq!(
3464            first_error_info("%YAML 9.9\n--- a\n"),
3465            "unsupported YAML major version"
3466        );
3467    }
3468
3469    #[test]
3470    fn test_document_start_emits_yaml_version() {
3471        let events = Parser::new_from_str("%YAML 1.2\n---\nvalue\n")
3472            .map(|event| event.unwrap().0)
3473            .collect::<Vec<_>>();
3474
3475        assert!(matches!(
3476            events.get(1),
3477            Some(Event::DocumentStart(
3478                true,
3479                Some(YamlVersion { major: 1, minor: 2 })
3480            ))
3481        ));
3482    }
3483
3484    #[test]
3485    fn test_document_start_allows_supported_major_future_minor_version() {
3486        let events = Parser::new_from_str("%YAML 1.9\n---\nvalue\n")
3487            .map(|event| event.unwrap().0)
3488            .collect::<Vec<_>>();
3489
3490        assert!(matches!(
3491            events.get(1),
3492            Some(Event::DocumentStart(
3493                true,
3494                Some(YamlVersion { major: 1, minor: 9 })
3495            ))
3496        ));
3497    }
3498
3499    #[test]
3500    fn test_document_start_keeps_version_and_tags_across_comment() {
3501        let events = Parser::new_from_str(
3502            "%YAML 1.2\n# directive comment\n%TAG !e! tag:example.com,2026:\n---\nkey: !e!thing value\n",
3503        )
3504        .map(|event| event.unwrap().0)
3505        .collect::<Vec<_>>();
3506
3507        assert!(matches!(
3508            events.get(2),
3509            Some(Event::DocumentStart(
3510                true,
3511                Some(YamlVersion { major: 1, minor: 2 })
3512            ))
3513        ));
3514
3515        let tag = events
3516            .iter()
3517            .find_map(|event| match event {
3518                Event::Scalar(value, _, _, Some(tag)) if value == "value" => Some(tag),
3519                _ => None,
3520            })
3521            .expect("expected tagged scalar after comment-separated directives");
3522
3523        assert_eq!(tag.handle, "tag:example.com,2026:");
3524        assert_eq!(tag.suffix, "thing");
3525    }
3526
3527    #[test]
3528    fn tag_directive_state_borrows_str_input_across_comment() {
3529        let mut parser = Parser::new_from_str(
3530            "%TAG !e! tag:example.com,2026:\n# directive comment\n---\nkey: value\n",
3531        );
3532
3533        while let Some(event) = parser.next_event() {
3534            if matches!(event.unwrap().0, Event::Comment(..)) {
3535                break;
3536            }
3537        }
3538
3539        assert!(matches!(
3540            parser.tags.get("!e!"),
3541            Some(Cow::Borrowed("tag:example.com,2026:"))
3542        ));
3543        assert!(parser
3544            .pending_document_tag_handles
3545            .iter()
3546            .any(|handle| matches!(handle, Cow::Borrowed("!e!"))));
3547    }
3548
3549    #[test]
3550    fn test_each_document_can_declare_own_yaml_version() {
3551        let document_starts = Parser::new_from_str(
3552            "%YAML 1.2\n---\na\n...\n%YAML 1.2\n---\nb\n...\n%YAML 1.1\n---\nc\n",
3553        )
3554        .filter_map(|event| match event.unwrap().0 {
3555            Event::DocumentStart(explicit, version) => Some((explicit, version)),
3556            _ => None,
3557        })
3558        .collect::<Vec<_>>();
3559
3560        assert_eq!(
3561            document_starts,
3562            vec![
3563                (true, Some(YamlVersion::new(1, 2))),
3564                (true, Some(YamlVersion::new(1, 2))),
3565                (true, Some(YamlVersion::new(1, 1))),
3566            ]
3567        );
3568    }
3569
3570    #[cfg(feature = "error_messages")]
3571    #[test]
3572    fn test_duplicate_tag_directive_errors() {
3573        assert_eq!(
3574            first_error_info("%TAG !t! tag:test,2024:\n%TAG !t! tag:other,2024:\n---\n"),
3575            "the TAG directive must only be given at most once per handle in the same document"
3576        );
3577    }
3578
3579    #[cfg(feature = "error_messages")]
3580    #[test]
3581    fn duplicate_tag_directive_across_comment_is_rejected() {
3582        let input = concat!(
3583            "%TAG !e! tag:example.com,2000:one/\n",
3584            "# separator\n",
3585            "%TAG !e! tag:example.com,2000:two/\n",
3586            "---\n",
3587        );
3588
3589        assert_eq!(
3590            first_error_info(input),
3591            "the TAG directive must only be given at most once per handle in the same document"
3592        );
3593    }
3594
3595    #[test]
3596    fn test_keep_tags_inherited_handle_can_be_redeclared_in_next_document() {
3597        let input = concat!(
3598            "%TAG !e! tag:example.com,2000:one/\n",
3599            "---\n",
3600            "first: !e!thing value\n",
3601            "...\n",
3602            "%TAG !e! tag:example.com,2000:two/\n",
3603            "---\n",
3604            "second: !e!thing value\n",
3605        );
3606
3607        let tags = Parser::new_from_str(input)
3608            .keep_tags(true)
3609            .filter_map(|event| match event.expect("input should parse").0 {
3610                Event::Scalar(value, _, _, Some(tag)) if value == "value" => {
3611                    Some(tag.handle.clone())
3612                }
3613                _ => None,
3614            })
3615            .collect::<Vec<_>>();
3616
3617        assert_eq!(
3618            tags,
3619            vec!["tag:example.com,2000:one/", "tag:example.com,2000:two/"]
3620        );
3621    }
3622
3623    #[cfg(feature = "error_messages")]
3624    #[test]
3625    fn test_directive_after_implicit_document_requires_explicit_end() {
3626        assert_eq!(
3627            first_error_info("---\nkey: value\n%YAML 1.2\n---\n"),
3628            "missing explicit document end marker before directive"
3629        );
3630    }
3631
3632    #[cfg(feature = "error_messages")]
3633    #[test]
3634    fn test_anchor_offset_overflow_reports_error() {
3635        let mut parser = Parser::new_from_str("&a value");
3636        parser.set_anchor_offset(usize::MAX);
3637
3638        let err = parser
3639            .find_map(Result::err)
3640            .expect("anchor registration should overflow");
3641
3642        assert_eq!(
3643            err.info(),
3644            "while parsing anchor, anchor count exceeded supported limit"
3645        );
3646    }
3647
3648    #[test]
3649    fn test_alias_resolves_to_registered_anchor_id() {
3650        let events = Parser::new_from_str("- &a value\n- *a\n")
3651            .map(|event| event.unwrap().0)
3652            .collect::<Vec<_>>();
3653
3654        assert!(events.iter().any(|event| matches!(event, Event::Alias(1))));
3655    }
3656
3657    #[test]
3658    fn test_anchor_then_tag_applies_both_to_scalar() {
3659        let events = Parser::new_from_str("&a !!str value")
3660            .map(|event| event.unwrap().0)
3661            .collect::<Vec<_>>();
3662
3663        let Some(Event::Scalar(value, _, anchor_id, Some(tag))) = events
3664            .iter()
3665            .find(|event| matches!(event, Event::Scalar(value, ..) if value == "value"))
3666        else {
3667            panic!("expected tagged anchored scalar");
3668        };
3669
3670        assert_eq!(value, "value");
3671        assert_eq!(*anchor_id, 1);
3672        assert_eq!(tag.handle, "tag:yaml.org,2002:");
3673        assert_eq!(tag.suffix, "str");
3674        assert_eq!(tag.original_handle, "!!");
3675        assert_eq!(tag.original(), "!!str");
3676    }
3677
3678    #[test]
3679    fn test_tag_then_anchor_applies_both_to_scalar() {
3680        let events = Parser::new_from_str("!!str &a value")
3681            .map(|event| event.unwrap().0)
3682            .collect::<Vec<_>>();
3683
3684        let Some(Event::Scalar(value, _, anchor_id, Some(tag))) = events
3685            .iter()
3686            .find(|event| matches!(event, Event::Scalar(value, ..) if value == "value"))
3687        else {
3688            panic!("expected tagged anchored scalar");
3689        };
3690
3691        assert_eq!(value, "value");
3692        assert_eq!(*anchor_id, 1);
3693        assert_eq!(tag.handle, "tag:yaml.org,2002:");
3694        assert_eq!(tag.suffix, "str");
3695        assert_eq!(tag.original_handle, "!!");
3696        assert_eq!(tag.original(), "!!str");
3697    }
3698
3699    #[test]
3700    fn test_tag_directive_preserves_original_handle() {
3701        let events =
3702            Parser::new_from_str("%TAG !e! tag:example.com,2000:\n---\nconfig: !e!keep value\n")
3703                .map(|event| event.unwrap().0)
3704                .collect::<Vec<_>>();
3705
3706        let (value, tag) = events
3707            .iter()
3708            .find_map(|event| match event {
3709                Event::Scalar(value, _, _, Some(tag)) if value == "value" => Some((value, tag)),
3710                _ => None,
3711            })
3712            .expect("expected tagged scalar");
3713
3714        assert_eq!(value, "value");
3715        assert_eq!(tag.handle, "tag:example.com,2000:");
3716        assert_eq!(tag.suffix, "keep");
3717        assert_eq!(tag.original_handle, "!e!");
3718        assert_eq!(tag.parts(), ("tag:example.com,2000:", "keep"));
3719        assert_eq!(tag.original_parts(), ("!e!", "keep"));
3720        assert_eq!(tag.original(), "!e!keep");
3721    }
3722
3723    #[test]
3724    fn test_verbatim_tag_original_is_normalized_author_spelling() {
3725        let events = Parser::new_from_str("key: !<tag:example.com,2000:thing> value\n")
3726            .map(|event| event.unwrap().0)
3727            .collect::<Vec<_>>();
3728
3729        let Some(Event::Scalar(value, _, _, Some(tag))) = events
3730            .iter()
3731            .find(|event| matches!(event, Event::Scalar(value, ..) if value == "value"))
3732        else {
3733            panic!("expected tagged scalar");
3734        };
3735
3736        assert_eq!(value, "value");
3737        assert_eq!(tag.handle, "");
3738        assert_eq!(tag.suffix, "tag:example.com,2000:thing");
3739        assert_eq!(tag.original_handle, "");
3740        assert_eq!(tag.parts(), ("", "tag:example.com,2000:thing"));
3741        assert_eq!(tag.original_parts(), ("", "tag:example.com,2000:thing"));
3742        assert_eq!(tag.original(), "!<tag:example.com,2000:thing>");
3743    }
3744
3745    #[test]
3746    fn test_multiple_tag_directives_are_kept_within_document() {
3747        let text = r"
3748%TAG !a! tag:a,2024:
3749%TAG !b! tag:b,2024:
3750---
3751first: !a!x foo
3752second: !b!y bar
3753";
3754
3755        let mut seen_a = false;
3756        let mut seen_b = false;
3757        for event in Parser::new_from_str(text) {
3758            let (event, _) = event.unwrap();
3759            if let Event::Scalar(_, _, _, Some(tag)) = event {
3760                if tag.handle == "tag:a,2024:" {
3761                    seen_a = true;
3762                } else if tag.handle == "tag:b,2024:" {
3763                    seen_b = true;
3764                }
3765            }
3766        }
3767
3768        assert!(seen_a);
3769        assert!(seen_b);
3770    }
3771
3772    #[cfg(feature = "error_messages")]
3773    #[test]
3774    fn test_tags_are_cleared_when_next_document_has_no_directives() {
3775        let text = r"
3776%TAG !t! tag:test,2024:
3777--- !t!1
3778foo
3779--- !t!2
3780bar
3781";
3782
3783        let mut parser = Parser::new_from_str(text);
3784        for event in parser.by_ref() {
3785            let (event, _) = event.unwrap();
3786            if let Event::DocumentEnd = event {
3787                break;
3788            }
3789        }
3790
3791        match parser.next().unwrap().unwrap().0 {
3792            Event::DocumentStart(true, None) => {}
3793            _ => panic!("expected explicit second document start"),
3794        }
3795
3796        let err = parser.next().unwrap().unwrap_err();
3797        assert!(format!("{err}").contains("the handle wasn't declared"));
3798    }
3799
3800    #[cfg(feature = "error_messages")]
3801    #[test]
3802    fn test_pull_parser_clears_anchors_between_documents() {
3803        let mut parser = Parser::new_from_str(
3804            "--- &a value
3805--- *a
3806",
3807        );
3808
3809        for event in parser.by_ref() {
3810            let (event, _) = event.unwrap();
3811            if matches!(event, Event::DocumentEnd) {
3812                break;
3813            }
3814        }
3815
3816        match parser.next().unwrap().unwrap().0 {
3817            Event::DocumentStart(true, None) => {}
3818            _ => panic!("expected explicit second document start"),
3819        }
3820
3821        let err = parser.next().unwrap().unwrap_err();
3822        assert!(format!("{err}").contains("unknown anchor"));
3823    }
3824
3825    #[test]
3826    fn test_keep_tags_across_multiple_documents() {
3827        let text = r#"
3828%YAML 1.1
3829%TAG !t! tag:test,2024:
3830--- !t!1 &1
3831foo: "bar"
3832--- !t!2 &2
3833baz: "qux"
3834"#;
3835        for x in Parser::new_from_str(text).keep_tags(true) {
3836            let x = x.unwrap();
3837            if let Event::MappingStart(_, _, tag) = x.0 {
3838                let tag = tag.unwrap();
3839                assert_eq!(tag.handle, "tag:test,2024:");
3840            }
3841        }
3842
3843        for x in Parser::new_from_str(text).keep_tags(false) {
3844            if x.is_err() {
3845                // Test successful
3846                return;
3847            }
3848        }
3849        panic!("Test failed, did not encounter error")
3850    }
3851
3852    #[test]
3853    fn test_flow_sequence_mapping_allows_empty_key() {
3854        let parser = Parser::new_from_str("[?: value]");
3855        for event in parser {
3856            event.expect("parser should accept flow sequence mappings with empty keys");
3857        }
3858    }
3859
3860    #[test]
3861    fn test_keep_tags_does_not_persist_default_tag_handles() {
3862        let text = "%TAG !! tag:evil,2024:\n--- !!int 1\n--- !!int 2\n";
3863
3864        let mut int_tags = Vec::new();
3865        for event in Parser::new_from_str(text).keep_tags(true) {
3866            let event = event.unwrap().0;
3867            if let Event::Scalar(_, _, _, Some(tag)) = event {
3868                if tag.suffix == "int" {
3869                    int_tags.push(tag.handle.clone());
3870                }
3871            }
3872        }
3873
3874        assert_eq!(int_tags, vec!["tag:evil,2024:", "tag:yaml.org,2002:"]);
3875    }
3876
3877    #[test]
3878    fn test_keep_tags_does_not_persist_primary_tag_handle() {
3879        let text = "%TAG ! tag:evil,2024:\n--- !int 1\n--- !int 2\n";
3880
3881        let tags = Parser::new_from_str(text)
3882            .keep_tags(true)
3883            .filter_map(|event| match event.expect("input should parse").0 {
3884                Event::Scalar(_, _, _, Some(tag)) if tag.suffix == "int" => {
3885                    Some(tag.handle.clone())
3886                }
3887                _ => None,
3888            })
3889            .collect::<Vec<_>>();
3890
3891        assert_eq!(tags, vec!["tag:evil,2024:", "!"]);
3892    }
3893
3894    #[test]
3895    fn test_resolve_tag_uses_overridden_local_prefix() {
3896        let mut parser = Parser::new_from_str("");
3897        parser
3898            .tags
3899            .insert("!".into(), "tag:local.example,2024:".into());
3900
3901        let tag = parser
3902            .resolve_tag(
3903                Span::empty(Marker::new(0, 1, 0)),
3904                &Cow::Borrowed(""),
3905                Cow::Borrowed("!"),
3906            )
3907            .unwrap();
3908
3909        assert_eq!(tag.handle, "tag:local.example,2024:");
3910        assert_eq!(tag.suffix, "!");
3911    }
3912
3913    #[test]
3914    fn test_load_after_peek_stream_start() {
3915        #[derive(Default)]
3916        struct Sink<'input> {
3917            events: Vec<Event<'input>>,
3918        }
3919
3920        impl<'input> EventReceiver<'input> for Sink<'input> {
3921            fn on_event(&mut self, ev: Event<'input>) {
3922                self.events.push(ev);
3923            }
3924        }
3925
3926        let mut parser = Parser::new_from_str("key: value\n");
3927        let mut sink = Sink::default();
3928
3929        assert_eq!(parser.peek().unwrap().unwrap().0, Event::StreamStart);
3930        parser.load(&mut sink, false).unwrap();
3931
3932        assert!(matches!(sink.events.first(), Some(Event::StreamStart)));
3933        assert!(matches!(sink.events.get(1), Some(Event::DocumentStart(..))));
3934    }
3935}