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