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