1use crate::{
8 error::{ErrorKind, ScanError},
9 input::{str::StrInput, BorrowedInput},
10 scanner::{Marker, Placement, QueuedToken, QueuedTokenType, ScalarStyle, Scanner, Span},
11 BufferedInput, FallibleBufferedInput, Options,
12};
13
14use alloc::{
15 borrow::Cow,
16 collections::{BTreeMap, BTreeSet, VecDeque},
17 string::{String, ToString},
18 vec::Vec,
19};
20use core::{
21 convert::Infallible,
22 fmt::{self, Display},
23};
24
25#[derive(Clone, Copy, PartialEq, Debug, Eq)]
26enum State {
27 StreamStart,
28 ImplicitDocumentStart,
29 DocumentStart,
30 DocumentContent,
31 DocumentEnd,
32 BlockNode,
33 BlockNodeOrIndentlessSequence,
34 FlowNode,
35 BlockSequenceFirstEntry,
36 BlockSequenceEntry,
37 IndentlessSequenceEntry,
38 IndentlessSequenceEntryNode,
39 BlockMappingFirstKey,
40 BlockMappingKey,
41 BlockMappingKeyNode,
42 BlockMappingValue,
43 BlockMappingValueNode,
44 FlowSequenceFirstEntry,
45 FlowSequenceEntry,
46 FlowSequenceEntryMappingKey,
47 FlowSequenceEntryMappingValue,
48 FlowSequenceEntryMappingValueNode,
49 FlowSequenceEntryMappingEnd,
50 FlowMappingFirstKey,
51 FlowMappingKey,
52 FlowMappingKeyNode,
53 FlowMappingValue,
54 FlowMappingValueNode,
55 FlowMappingEmptyValue,
56 BlockSequenceEntryNode,
57 End,
58}
59
60#[derive(Copy, Clone, PartialEq, Debug, Eq, Hash)]
62pub struct YamlVersion {
63 pub major: u32,
65 pub minor: u32,
67}
68
69impl YamlVersion {
70 #[must_use]
72 pub const fn new(major: u32, minor: u32) -> Self {
73 Self { major, minor }
74 }
75}
76
77#[non_exhaustive]
82#[derive(Clone, PartialEq, Debug, Eq)]
83pub enum Event<'input> {
84 StreamStart,
86 StreamEnd,
88 DocumentStart(
91 bool,
95 Option<YamlVersion>,
97 ),
98 DocumentEnd,
103 Alias(
105 usize,
107 ),
108 Comment(
115 Cow<'input, str>,
117 Placement,
119 ),
120 Scalar(
122 Cow<'input, str>,
124 ScalarStyle,
126 usize,
128 Option<Cow<'input, Tag>>,
130 ),
131 SequenceStart(
133 StructureStyle,
135 usize,
137 Option<Cow<'input, Tag>>,
139 ),
140 SequenceEnd,
142 MappingStart(
144 StructureStyle,
146 usize,
148 Option<Cow<'input, Tag>>,
150 ),
151 MappingEnd,
153}
154
155#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)]
175pub enum StructureStyle {
176 Block,
178 Flow,
180}
181
182#[derive(Clone, PartialEq, Debug, Eq, Ord, PartialOrd, Hash)]
184pub struct Tag {
185 handle: String,
189 suffix: String,
191 original_handle: String,
197}
198
199const YAML_CORE_SCHEMA_PREFIX: &str = "tag:yaml.org,2002:";
200
201const 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 #[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 #[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 #[must_use]
257 pub fn handle(&self) -> &str {
258 &self.handle
259 }
260
261 #[must_use]
263 pub fn suffix(&self) -> &str {
264 &self.suffix
265 }
266
267 #[must_use]
269 pub fn original_handle(&self) -> &str {
270 &self.original_handle
271 }
272
273 #[must_use]
282 pub fn core_suffix(&self) -> Option<&str> {
283 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 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 #[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 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 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 #[must_use]
338 pub fn is_yaml_core_schema(&self) -> bool {
339 self.core_suffix().is_some()
340 }
341
342 #[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 #[must_use]
358 pub fn is_custom(&self) -> bool {
359 !self.is_yaml_core_schema()
360 }
361
362 #[must_use]
364 pub fn parts(&self) -> (&str, &str) {
365 (&self.handle, &self.suffix)
366 }
367
368 #[must_use]
373 pub fn original_parts(&self) -> (&str, &str) {
374 (&self.original_handle, &self.suffix)
375 }
376
377 #[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 #[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 #[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 #[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 #[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 #[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 fn empty_scalar() -> Self {
473 Event::Scalar("~".into(), ScalarStyle::Plain, 0, None)
475 }
476
477 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#[derive(Debug)]
491pub struct Parser<'input, T: BorrowedInput<'input>> {
492 scanner: Scanner<'input, T>,
494 max_buffered_comment_events: usize,
496 block_nesting_limit: usize,
498 block_level: usize,
500 states: Vec<State>,
505 state: State,
507 token: Option<QueuedToken<'input>>,
509 current: Option<(Event<'input>, Span)>,
511 current_error: Option<ScanError>,
513 deferred_error: Option<ScanError>,
519 queued_events: VecDeque<(Event<'input>, Span)>,
521
522 pending_key_indent: Option<usize>,
528 pending_node_anchor_id: usize,
530 pending_node_tag: Option<Cow<'input, Tag>>,
532 pending_node_tag_start: Option<Marker>,
534 pending_node_property_end: Option<Marker>,
536 pending_empty_scalar_span: Option<Span>,
538 last_non_comment_event_end: Option<Marker>,
542 pending_document_version: Option<YamlVersion>,
544 pending_document_directives: bool,
546 pending_document_tag_handles: BTreeSet<Cow<'input, str>>,
548 anchors: BTreeMap<Cow<'input, str>, usize>,
550 anchor_id_count: usize,
555 tags: BTreeMap<Cow<'input, str>, Cow<'input, str>>,
559 stream_end_emitted: bool,
566 keep_tags: bool,
568}
569
570pub trait EventReceiver<'input> {
650 fn on_event(&mut self, ev: Event<'input>);
652}
653
654pub trait SpannedEventReceiver<'input> {
659 fn on_event(&mut self, ev: Event<'input>, span: Span);
661}
662
663impl<'input, R: EventReceiver<'input>> SpannedEventReceiver<'input> for R {
664 fn on_event(&mut self, ev: Event<'input>, _span: Span) {
665 self.on_event(ev);
666 }
667}
668
669pub trait TryEventReceiver<'input> {
674 type Error;
676
677 fn on_event(&mut self, ev: Event<'input>) -> Result<(), Self::Error>;
684}
685
686pub trait TrySpannedEventReceiver<'input> {
692 type Error;
694
695 fn on_event(&mut self, ev: Event<'input>, span: Span) -> Result<(), Self::Error>;
702}
703
704impl<'input, R: TryEventReceiver<'input>> TrySpannedEventReceiver<'input> for R {
705 type Error = R::Error;
706
707 fn on_event(&mut self, ev: Event<'input>, _span: Span) -> Result<(), Self::Error> {
708 TryEventReceiver::on_event(self, ev)
709 }
710}
711
712#[derive(Clone, PartialEq, Debug, Eq)]
714pub enum TryLoadError<E> {
715 Scan(
717 ScanError,
719 ),
720 Receiver(
722 E,
724 ),
725}
726
727impl<E> TryLoadError<E> {
728 #[cold]
729 fn scan(error: ScanError) -> Self {
730 Self::Scan(error)
731 }
732
733 #[cold]
734 fn receiver(error: E) -> Self {
735 Self::Receiver(error)
736 }
737}
738
739impl<E> From<ScanError> for TryLoadError<E> {
740 #[cold]
741 fn from(error: ScanError) -> Self {
742 Self::scan(error)
743 }
744}
745
746impl<E: Display> Display for TryLoadError<E> {
747 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
748 match self {
749 Self::Scan(error) => write!(f, "parser error: {error}"),
750 Self::Receiver(error) => write!(f, "receiver error: {error}"),
751 }
752 }
753}
754
755impl<E> core::error::Error for TryLoadError<E>
756where
757 E: core::error::Error + 'static,
758{
759 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
760 match self {
761 Self::Scan(error) => Some(error),
762 Self::Receiver(error) => Some(error),
763 }
764 }
765}
766
767fn try_emit<'input, R>(
768 recv: &mut R,
769 ev: Event<'input>,
770 span: Span,
771) -> Result<(), TryLoadError<R::Error>>
772where
773 R: TrySpannedEventReceiver<'input>,
774{
775 recv.on_event(ev, span).map_err(TryLoadError::receiver)
776}
777
778struct InfallibleSpannedReceiver<'receiver, R>(&'receiver mut R);
779
780impl<'input, R: SpannedEventReceiver<'input>> TrySpannedEventReceiver<'input>
781 for InfallibleSpannedReceiver<'_, R>
782{
783 type Error = Infallible;
784
785 fn on_event(&mut self, ev: Event<'input>, span: Span) -> Result<(), Self::Error> {
786 self.0.on_event(ev, span);
787 Ok(())
788 }
789}
790
791fn into_scan_result(result: Result<(), TryLoadError<Infallible>>) -> Result<(), ScanError> {
792 match result {
793 Ok(()) => Ok(()),
794 Err(TryLoadError::Scan(error)) => error.into_result(),
795 Err(TryLoadError::Receiver(error)) => match error {},
796 }
797}
798
799pub type ParseResult<'input> = Result<(Event<'input>, Span), ScanError>;
801
802pub trait ParserTrait<'input> {
804 fn peek(&mut self) -> Option<Result<&(Event<'input>, Span), ScanError>>;
806
807 fn next_event(&mut self) -> Option<ParseResult<'input>>;
809
810 fn load<R: SpannedEventReceiver<'input>>(
820 &mut self,
821 recv: &mut R,
822 multi: bool,
823 ) -> Result<(), ScanError>;
824
825 fn try_load<R: TrySpannedEventReceiver<'input>>(
837 &mut self,
838 recv: &mut R,
839 multi: bool,
840 ) -> Result<(), TryLoadError<R::Error>> {
841 while let Some(res) = self.next_event() {
842 let (ev, span) = res?;
843 let is_doc_end = matches!(ev, Event::DocumentEnd);
844 let is_stream_end = matches!(ev, Event::StreamEnd);
845
846 try_emit(recv, ev, span)?;
847
848 if is_stream_end {
849 break;
850 }
851 if !multi && is_doc_end {
852 break;
853 }
854 }
855
856 Ok(())
857 }
858}
859
860impl<'input> Parser<'input, StrInput<'input>> {
861 #[must_use]
863 pub fn new_from_str(value: &'input str) -> Self {
864 Self::new_from_str_with_options(value, Options::default())
865 }
866
867 #[must_use]
870 pub fn new_from_str_with_options(value: &'input str, options: Options) -> Self {
871 Parser::with_options(StrInput::new(value), options)
872 }
873}
874
875impl<T> Parser<'static, BufferedInput<T>>
876where
877 T: Iterator<Item = char>,
878{
879 #[must_use]
881 pub fn new_from_iter(iter: T) -> Self {
882 Self::new_from_iter_with_options(iter, Options::default())
883 }
884
885 #[must_use]
888 pub fn new_from_iter_with_options(iter: T, options: Options) -> Self {
889 Parser::with_options(BufferedInput::new(iter), options)
890 }
891}
892
893impl<T> Parser<'static, FallibleBufferedInput<T>>
894where
895 T: Iterator<Item = Result<char, ErrorKind>>,
896{
897 #[must_use]
903 pub fn new_from_fallible_iter(iter: T) -> Self {
904 Self::new_from_fallible_iter_with_options(iter, Options::default())
905 }
906
907 #[must_use]
914 pub fn new_from_fallible_iter_with_options(iter: T, options: Options) -> Self {
915 Parser::with_options(FallibleBufferedInput::new(iter), options)
916 }
917}
918
919impl<'input, T: BorrowedInput<'input>> Parser<'input, T> {
920 #[must_use]
922 pub fn anchor_offset(&self) -> usize {
923 self.anchor_id_count
924 }
925
926 pub fn set_anchor_offset(&mut self, offset: usize) {
928 self.anchor_id_count = offset;
929 }
930
931 #[must_use]
933 pub fn new(src: T) -> Self {
934 Self::with_options(src, Options::default())
935 }
936
937 #[must_use]
942 pub fn with_options(src: T, options: Options) -> Self {
943 let max_buffered_comment_events = options.max_buffered_comment_events;
944 let block_nesting_limit = options.block_nesting_limit;
945
946 Parser {
947 scanner: Scanner::with_options(src, options),
948 max_buffered_comment_events,
949 block_nesting_limit,
950 block_level: 0,
951 states: Vec::new(),
952 state: State::StreamStart,
953 token: None,
954 current: None,
955 current_error: None,
956 deferred_error: None,
957 queued_events: VecDeque::new(),
958
959 pending_key_indent: None,
960 pending_node_anchor_id: 0,
961 pending_node_tag: None,
962 pending_node_tag_start: None,
963 pending_node_property_end: None,
964 pending_empty_scalar_span: None,
965 last_non_comment_event_end: None,
966 pending_document_version: None,
967 pending_document_directives: false,
968 pending_document_tag_handles: BTreeSet::new(),
969
970 anchors: BTreeMap::new(),
971 anchor_id_count: 1,
973 tags: BTreeMap::new(),
974 stream_end_emitted: false,
975 keep_tags: false,
976 }
977 }
978
979 #[must_use]
1002 pub fn keep_tags(mut self, value: bool) -> Self {
1003 self.keep_tags = value;
1004 self
1005 }
1006
1007 pub fn peek(&mut self) -> Option<Result<&(Event<'input>, Span), ScanError>> {
1017 ParserTrait::peek(self)
1018 }
1019
1020 pub fn next_event(&mut self) -> Option<ParseResult<'input>> {
1027 ParserTrait::next_event(self)
1028 }
1029
1030 fn next_event_impl<'a>(&mut self) -> ParseResult<'a>
1036 where
1037 'input: 'a,
1038 {
1039 let event = match self.current.take() {
1040 None => {
1041 if let Some(event) = self.queued_events.pop_front() {
1042 Ok(self.apply_pending_key_indent(event))
1043 } else if let Some(error) = self.deferred_error.take() {
1044 return Err(error);
1045 } else if self.state == State::End {
1046 self.parse()
1047 } else if let Some(comment) = self.maybe_next_comment_event()? {
1048 Ok(comment)
1049 } else {
1050 self.parse()
1051 }
1052 }
1053 Some(v) => Ok(v),
1054 }?;
1055
1056 Ok(self.remember_non_comment_event_end(event))
1057 }
1058
1059 fn apply_pending_key_indent<'a>(&mut self, (ev, span): (Event<'a>, Span)) -> (Event<'a>, Span) {
1060 if ev.is_node() {
1061 if let Some(indent) = self.pending_key_indent.take() {
1062 return (ev, span.with_indent(Some(indent)));
1063 }
1064 }
1065
1066 (ev, span)
1067 }
1068
1069 fn remember_non_comment_event_end<'a>(
1070 &mut self,
1071 (event, span): (Event<'a>, Span),
1072 ) -> (Event<'a>, Span) {
1073 if !matches!(event, Event::Comment(..)) {
1074 self.last_non_comment_event_end = Some(span.end);
1075 }
1076 (event, span)
1077 }
1078
1079 fn peek_token(&mut self) -> Result<&QueuedToken<'_>, ScanError> {
1081 if let Some(error) = &self.deferred_error {
1082 return Err(error.clone());
1083 }
1084
1085 match self.token {
1086 None => {
1087 self.token = Some(self.scan_next_token()?);
1088 Ok(self.token.as_ref().unwrap())
1089 }
1090 Some(ref tok) => Ok(tok),
1091 }
1092 }
1093
1094 fn scan_next_token(&mut self) -> Result<QueuedToken<'input>, ScanError> {
1098 match self.scanner.next_queued_token()? {
1099 None => unreachable!("scanner ended before the parser consumed its stream-end token"),
1100 Some(tok) => Ok(tok),
1101 }
1102 }
1103
1104 #[inline]
1105 fn maybe_next_comment_event<'a>(&mut self) -> Result<Option<(Event<'a>, Span)>, ScanError>
1106 where
1107 'input: 'a,
1108 {
1109 if self.scanner.comments_possible() {
1110 self.next_comment_event()
1111 } else {
1112 Ok(None)
1113 }
1114 }
1115
1116 fn next_comment_event<'a>(&mut self) -> Result<Option<(Event<'a>, Span)>, ScanError>
1117 where
1118 'input: 'a,
1119 {
1120 let is_comment = {
1121 let token = self.peek_token()?;
1122 matches!(token.1, QueuedTokenType::Comment(_))
1123 };
1124
1125 if !is_comment {
1126 return Ok(None);
1127 }
1128
1129 let QueuedToken(span, token) = self.fetch_token();
1130 match token {
1131 QueuedTokenType::Comment(comment) => {
1132 let placement = self.refined_comment_placement(span, comment.placement());
1133 Ok(Some((Event::Comment(comment.into_text(), placement), span)))
1134 }
1135 _ => unreachable!("comment token disappeared after peek"),
1136 }
1137 }
1138
1139 #[inline]
1140 fn next_comment_events(&mut self) -> Result<Vec<(Event<'input>, Span)>, ScanError> {
1141 if !self.scanner.comments_possible() {
1142 return Ok(Vec::new());
1143 }
1144
1145 let mut events = Vec::new();
1146 loop {
1147 match self.peek_token() {
1148 Ok(token) if matches!(token.1, QueuedTokenType::Comment(_)) => {}
1149 Err(error) if events.is_empty() => return Err(error),
1150 Err(error) => {
1151 debug_assert!(self.deferred_error.is_none());
1152 self.deferred_error = Some(error);
1153 return Ok(events);
1154 }
1155 Ok(_) => return Ok(events),
1156 }
1157
1158 if events.len() >= self.max_buffered_comment_events {
1159 return Err(ScanError::from_kind(
1160 self.peek_token()?.0.start,
1161 ErrorKind::TooManyComments,
1162 ));
1163 }
1164
1165 let comment = self
1166 .next_comment_event()?
1167 .expect("comment token disappeared after peek");
1168 events.push(comment);
1169 if self.deferred_error.is_some() {
1170 return Ok(events);
1171 }
1172 }
1173 }
1174
1175 fn queue_tail_and_return_first(
1176 &mut self,
1177 events: Vec<(Event<'input>, Span)>,
1178 ) -> (Event<'input>, Span) {
1179 let mut events = events.into_iter();
1180 let first = events
1181 .next()
1182 .expect("event queue must contain at least one event");
1183 self.queued_events.extend(events);
1184 first
1185 }
1186
1187 fn queue_event_by_span(
1188 &mut self,
1189 comments: Vec<(Event<'input>, Span)>,
1190 event: (Event<'input>, Span),
1191 ) -> (Event<'input>, Span) {
1192 let insert_at = comments
1193 .iter()
1194 .position(|(_, comment_span)| {
1195 comment_span.start.index() >= event.1.start.index()
1196 && comment_span.end.index() >= event.1.end.index()
1197 })
1198 .unwrap_or(comments.len());
1199 let mut ordered = Vec::with_capacity(comments.len() + 1);
1200 let mut comments = comments.into_iter();
1201
1202 for _ in 0..insert_at {
1203 ordered.push(
1204 comments
1205 .next()
1206 .expect("comment disappeared while ordering queued events"),
1207 );
1208 }
1209 ordered.push(event);
1210 ordered.extend(comments);
1211
1212 self.queue_tail_and_return_first(ordered)
1213 }
1214
1215 fn queue_two_events_by_span(
1216 &mut self,
1217 comments: Vec<(Event<'input>, Span)>,
1218 first: (Event<'input>, Span),
1219 second: (Event<'input>, Span),
1220 ) -> (Event<'input>, Span) {
1221 let insert_at = comments
1222 .iter()
1223 .position(|(_, comment_span)| {
1224 comment_span.start.index() >= first.1.start.index()
1225 && comment_span.end.index() >= first.1.end.index()
1226 })
1227 .unwrap_or(comments.len());
1228 let mut ordered = Vec::with_capacity(comments.len() + 2);
1229 let mut comments = comments.into_iter();
1230
1231 for _ in 0..insert_at {
1232 ordered.push(
1233 comments
1234 .next()
1235 .expect("comment disappeared while ordering queued events"),
1236 );
1237 }
1238 ordered.push(first);
1239 ordered.push(second);
1240 ordered.extend(comments);
1241
1242 self.queue_tail_and_return_first(ordered)
1243 }
1244
1245 fn refined_comment_placement(&mut self, span: Span, placement: Placement) -> Placement {
1246 if placement == Placement::Right {
1247 return Placement::Right;
1248 }
1249
1250 let next = match self.peek_token() {
1251 Ok(next) => next,
1252 Err(error) => {
1253 debug_assert!(self.deferred_error.is_none());
1254 self.deferred_error = Some(error);
1255 return placement;
1256 }
1257 };
1258 if matches!(next.1, QueuedTokenType::StreamEnd) {
1259 return Placement::Last;
1260 }
1261
1262 if next.0.start.line() == span.end.line() + 1 {
1263 Placement::Above
1264 } else {
1265 Placement::Free
1266 }
1267 }
1268
1269 #[track_caller]
1274 fn fetch_token<'a>(&mut self) -> QueuedToken<'a>
1275 where
1276 'input: 'a,
1277 {
1278 self.token
1279 .take()
1280 .expect("fetch_token needs to be preceded by peek_token")
1281 }
1282
1283 fn skip(&mut self) {
1285 self.token = None;
1286 }
1287 #[track_caller]
1292 fn pop_state(&mut self) {
1293 self.state = self.states.pop().unwrap();
1294 }
1295 fn push_state(&mut self, state: State) {
1297 self.states.push(state);
1298 }
1299
1300 fn start_block_collection(&mut self, mark: Marker) -> Result<(), ScanError> {
1301 if self.block_level >= self.block_nesting_limit {
1302 return Err(ScanError::from_kind(
1303 mark,
1304 ErrorKind::RecursionLimitExceeded,
1305 ));
1306 }
1307 self.block_level += 1;
1308 Ok(())
1309 }
1310
1311 fn end_block_collection(&mut self) {
1312 debug_assert!(self.block_level > 0);
1313 self.block_level -= 1;
1314 }
1315
1316 fn defer_parse_node<'a>(
1317 &mut self,
1318 node_state: State,
1319 return_state: State,
1320 block: bool,
1321 indentless_sequence: bool,
1322 ) -> ParseResult<'a>
1323 where
1324 'input: 'a,
1325 {
1326 self.push_state(return_state);
1327 self.state = node_state;
1328 if let Some(comment) = self.maybe_next_comment_event()? {
1329 Ok(comment)
1330 } else {
1331 self.parse_node(block, indentless_sequence)
1332 }
1333 }
1334
1335 fn parse<'a>(&mut self) -> ParseResult<'a>
1336 where
1337 'input: 'a,
1338 {
1339 if self.state == State::End {
1340 return Ok((Event::StreamEnd, Span::empty(self.scanner.mark())));
1341 }
1342 let event = self.state_machine()?;
1343 Ok(self.apply_pending_key_indent(event))
1344 }
1345
1346 pub fn load<R: SpannedEventReceiver<'input>>(
1392 &mut self,
1393 recv: &mut R,
1394 multi: bool,
1395 ) -> Result<(), ScanError> {
1396 ParserTrait::load(self, recv, multi)
1397 }
1398
1399 pub fn try_load<R: TrySpannedEventReceiver<'input>>(
1444 &mut self,
1445 recv: &mut R,
1446 multi: bool,
1447 ) -> Result<(), TryLoadError<R::Error>> {
1448 ParserTrait::try_load(self, recv, multi)
1449 }
1450
1451 fn state_machine<'a>(&mut self) -> ParseResult<'a>
1452 where
1453 'input: 'a,
1454 {
1455 debug_print!("\n\x1B[;33mParser state: {:?} \x1B[;0m", self.state);
1456
1457 match self.state {
1458 State::StreamStart => self.stream_start(),
1459
1460 State::ImplicitDocumentStart => self.document_start(true),
1461 State::DocumentStart => self.document_start(false),
1462 State::DocumentContent => self.document_content(),
1463 State::DocumentEnd => self.document_end(),
1464
1465 State::BlockNode => self.parse_node(true, false),
1466 State::BlockNodeOrIndentlessSequence => self.parse_node(true, true),
1467 State::FlowNode => self.parse_node(false, false),
1468 State::BlockMappingFirstKey => self.block_mapping_key(true),
1469 State::BlockMappingKey => self.block_mapping_key(false),
1470 State::BlockMappingKeyNode => self.block_mapping_key_node(),
1471 State::BlockMappingValue => self.block_mapping_value(),
1472 State::BlockMappingValueNode => self.block_mapping_value_node(),
1473
1474 State::BlockSequenceFirstEntry => self.block_sequence_entry(true),
1475 State::BlockSequenceEntry => self.block_sequence_entry(false),
1476 State::BlockSequenceEntryNode => self.block_sequence_entry_node(),
1477
1478 State::FlowSequenceFirstEntry => self.flow_sequence_entry(true),
1479 State::FlowSequenceEntry => self.flow_sequence_entry(false),
1480
1481 State::FlowMappingFirstKey => self.flow_mapping_key(true),
1482 State::FlowMappingKey => self.flow_mapping_key(false),
1483 State::FlowMappingKeyNode => self.flow_mapping_key_node(),
1484 State::FlowMappingValue => self.flow_mapping_value(false),
1485 State::FlowMappingValueNode => self.flow_mapping_value_node(),
1486
1487 State::IndentlessSequenceEntry => self.indentless_sequence_entry(),
1488 State::IndentlessSequenceEntryNode => self.indentless_sequence_entry_node(),
1489
1490 State::FlowSequenceEntryMappingKey => self.flow_sequence_entry_mapping_key(),
1491 State::FlowSequenceEntryMappingValue => self.flow_sequence_entry_mapping_value(),
1492 State::FlowSequenceEntryMappingValueNode => {
1493 self.flow_sequence_entry_mapping_value_node()
1494 }
1495 State::FlowSequenceEntryMappingEnd => self.flow_sequence_entry_mapping_end(),
1496 State::FlowMappingEmptyValue => self.flow_mapping_value(true),
1497
1498 State::End => unreachable!("end state is handled before state-machine dispatch"),
1499 }
1500 }
1501
1502 fn stream_start<'a>(&mut self) -> ParseResult<'a>
1503 where
1504 'input: 'a,
1505 {
1506 match *self.peek_token()? {
1507 QueuedToken(span, QueuedTokenType::StreamStart) => {
1508 self.state = State::ImplicitDocumentStart;
1509 self.skip();
1510 Ok((Event::StreamStart, span))
1511 }
1512 QueuedToken(span, _) => Err(ScanError::from_kind(
1513 span.start,
1514 ErrorKind::ExpectedStreamStart,
1515 )),
1516 }
1517 }
1518
1519 fn has_pending_document_directives(&self) -> bool {
1520 self.pending_document_directives
1521 || self.pending_document_version.is_some()
1522 || !self.pending_document_tag_handles.is_empty()
1523 }
1524
1525 fn document_start<'a>(&mut self, implicit: bool) -> ParseResult<'a>
1526 where
1527 'input: 'a,
1528 {
1529 if self.has_pending_document_directives() {
1533 return self.explicit_document_start();
1534 }
1535
1536 while let QueuedTokenType::DocumentEnd = self.peek_token()?.1 {
1537 self.skip();
1538 }
1539
1540 self.anchors.clear();
1542
1543 if let Some(comment) = self.maybe_next_comment_event()? {
1547 return Ok(comment);
1548 }
1549
1550 match *self.peek_token()? {
1551 QueuedToken(span, QueuedTokenType::StreamEnd) => {
1552 self.state = State::End;
1553 self.skip();
1554 Ok((Event::StreamEnd, span))
1555 }
1556 QueuedToken(
1557 _,
1558 QueuedTokenType::VersionDirective(..)
1559 | QueuedTokenType::TagDirective(..)
1560 | QueuedTokenType::ReservedDirective(..)
1561 | QueuedTokenType::DocumentStart,
1562 ) => {
1563 self.explicit_document_start()
1565 }
1566 QueuedToken(span, _) if implicit => {
1567 self.parser_process_directives(None, false, BTreeSet::new())?;
1568 self.push_state(State::DocumentEnd);
1569 self.state = State::BlockNode;
1570 Ok((Event::DocumentStart(false, None), span))
1571 }
1572 _ => {
1573 self.explicit_document_start()
1575 }
1576 }
1577 }
1578
1579 fn parser_process_directives(
1580 &mut self,
1581 mut version: Option<YamlVersion>,
1582 continuing: bool,
1583 mut document_tag_handles: BTreeSet<Cow<'input, str>>,
1584 ) -> Result<(Option<YamlVersion>, BTreeSet<Cow<'input, str>>), ScanError> {
1585 let mut tags = if continuing || self.keep_tags {
1586 core::mem::take(&mut self.tags)
1587 } else {
1588 BTreeMap::new()
1589 };
1590
1591 loop {
1592 let is_directive = matches!(
1593 self.peek_token()?.1,
1594 QueuedTokenType::VersionDirective(..)
1595 | QueuedTokenType::TagDirective(..)
1596 | QueuedTokenType::ReservedDirective(..)
1597 );
1598 if !is_directive {
1599 break;
1600 }
1601
1602 let QueuedToken(span, token) = self.fetch_token();
1603 match token {
1604 QueuedTokenType::VersionDirective(major, minor) => {
1605 if version.is_some() {
1606 return Err(ScanError::from_kind(
1607 span.start,
1608 ErrorKind::DuplicateVersionDirective,
1609 ));
1610 }
1611 if major != 1 {
1612 return Err(ScanError::from_kind(
1613 span.start,
1614 ErrorKind::UnsupportedYamlMajorVersion,
1615 ));
1616 }
1617 version = Some(YamlVersion::new(major, minor));
1618 }
1619 QueuedTokenType::TagDirective(handle, prefix) => {
1620 if !document_tag_handles.insert(handle.clone()) {
1621 return Err(ScanError::from_kind(
1622 span.start,
1623 ErrorKind::DuplicateTagDirective,
1624 ));
1625 }
1626 tags.insert(handle, prefix);
1627 }
1628 QueuedTokenType::ReservedDirective(_, _) => {
1629 }
1631 _ => unreachable!("non-directive token passed the directive guard"),
1632 }
1633 }
1634
1635 self.tags = tags;
1636 Ok((version, document_tag_handles))
1637 }
1638
1639 fn explicit_document_start<'a>(&mut self) -> ParseResult<'a>
1640 where
1641 'input: 'a,
1642 {
1643 let pending_version = self.pending_document_version.take();
1644 let continuing_directives = core::mem::take(&mut self.pending_document_directives);
1645 let pending_tag_handles = core::mem::take(&mut self.pending_document_tag_handles);
1646 let (version, document_tag_handles) = self.parser_process_directives(
1647 pending_version,
1648 continuing_directives,
1649 pending_tag_handles,
1650 )?;
1651 if let Some(comment) = self.maybe_next_comment_event()? {
1652 self.pending_document_version = version;
1653 self.pending_document_directives = true;
1654 self.pending_document_tag_handles = document_tag_handles;
1655 return Ok(comment);
1656 }
1657 match *self.peek_token()? {
1658 QueuedToken(mark, QueuedTokenType::DocumentStart) => {
1659 self.push_state(State::DocumentEnd);
1660 self.state = State::DocumentContent;
1661 self.skip();
1662 Ok((Event::DocumentStart(true, version), mark))
1663 }
1664 QueuedToken(span, _) => Err(ScanError::from_kind(
1665 span.start,
1666 ErrorKind::ExpectedDocumentStart,
1667 )),
1668 }
1669 }
1670
1671 fn document_content<'a>(&mut self) -> ParseResult<'a>
1672 where
1673 'input: 'a,
1674 {
1675 if let QueuedToken(
1676 mark,
1677 QueuedTokenType::VersionDirective(..)
1678 | QueuedTokenType::TagDirective(..)
1679 | QueuedTokenType::ReservedDirective(..)
1680 | QueuedTokenType::DocumentStart
1681 | QueuedTokenType::DocumentEnd
1682 | QueuedTokenType::StreamEnd,
1683 ) = *self.peek_token()?
1684 {
1685 self.pop_state();
1686 let span = self
1687 .last_non_comment_event_end
1688 .map_or_else(|| Span::empty(mark.start), Span::empty);
1689 Ok((Event::empty_scalar(), span))
1690 } else {
1691 self.state = State::BlockNode;
1692 self.parse_node(true, false)
1693 }
1694 }
1695
1696 fn document_end<'a>(&mut self) -> ParseResult<'a>
1697 where
1698 'input: 'a,
1699 {
1700 let mut explicit_end = false;
1701 let span: Span = match *self.peek_token()? {
1702 QueuedToken(span, QueuedTokenType::DocumentEnd) => {
1703 explicit_end = true;
1704 self.skip();
1705 span
1706 }
1707 QueuedToken(span, _) => self
1708 .last_non_comment_event_end
1709 .map_or_else(|| Span::empty(span.start), Span::empty),
1710 };
1711
1712 if self.keep_tags {
1713 self.tags.remove("!!");
1717 self.tags.remove("!");
1718 } else {
1719 self.tags.clear();
1720 }
1721 if explicit_end {
1722 self.state = State::ImplicitDocumentStart;
1723 } else {
1724 if let QueuedToken(
1725 span,
1726 QueuedTokenType::VersionDirective(..)
1727 | QueuedTokenType::TagDirective(..)
1728 | QueuedTokenType::ReservedDirective(..),
1729 ) = *self.peek_token()?
1730 {
1731 return Err(ScanError::from_kind(
1732 span.start,
1733 ErrorKind::MissingDocumentEndBeforeDirective,
1734 ));
1735 }
1736 self.state = State::DocumentStart;
1737 }
1738
1739 Ok((Event::DocumentEnd, span))
1740 }
1741
1742 fn register_anchor(&mut self, name: Cow<'input, str>, mark: &Span) -> Result<usize, ScanError> {
1743 let new_id = self.anchor_id_count;
1745 self.anchor_id_count = self
1746 .anchor_id_count
1747 .checked_add(1)
1748 .ok_or_else(|| ScanError::from_kind(mark.start, ErrorKind::AnchorCountOverflow))?;
1749 self.anchors.insert(name, new_id);
1750 Ok(new_id)
1751 }
1752
1753 fn save_pending_node_properties(
1754 &mut self,
1755 anchor_id: usize,
1756 tag: Option<Cow<'input, Tag>>,
1757 tag_start: Option<Marker>,
1758 property_end: Option<Marker>,
1759 ) {
1760 self.pending_node_anchor_id = anchor_id;
1761 self.pending_node_tag = tag;
1762 self.pending_node_tag_start = tag_start;
1763 self.pending_node_property_end = property_end;
1764 }
1765
1766 fn attach_tag_start(event: Event<'_>, span: Span, start: Option<Marker>) -> (Event<'_>, Span) {
1767 (event, span.with_tag_start(start))
1768 }
1769
1770 #[allow(clippy::too_many_lines)]
1771 fn parse_node<'a>(&mut self, block: bool, indentless_sequence: bool) -> ParseResult<'a>
1772 where
1773 'input: 'a,
1774 {
1775 if let Some(comment) = self.maybe_next_comment_event()? {
1776 return Ok(comment);
1777 }
1778
1779 let mut anchor_id = core::mem::take(&mut self.pending_node_anchor_id);
1780 let mut tag = self.pending_node_tag.take();
1781 let mut tag_start = self.pending_node_tag_start.take();
1782 let mut property_end = self.pending_node_property_end.take();
1783 match *self.peek_token()? {
1784 QueuedToken(_, QueuedTokenType::Alias(_)) if anchor_id == 0 && tag.is_none() => {
1785 self.pop_state();
1786 let QueuedToken(span, QueuedTokenType::Alias(name)) = self.fetch_token() else {
1787 unreachable!("alias token disappeared after peek")
1788 };
1789 return match self.anchors.get(&*name) {
1790 None => Err(ScanError::from_kind(span.start, ErrorKind::UnknownAnchor)),
1791 Some(id) => Ok((Event::Alias(*id), span)),
1792 };
1793 }
1794 QueuedToken(_, QueuedTokenType::Anchor(_)) if anchor_id == 0 => {
1795 let QueuedToken(span, QueuedTokenType::Anchor(name)) = self.fetch_token() else {
1796 unreachable!("anchor token disappeared after peek")
1797 };
1798 anchor_id = self.register_anchor(name, &span)?;
1799 property_end = Some(span.end);
1800 if tag.is_none() && matches!(self.peek_token()?.1, QueuedTokenType::Tag(..)) {
1801 let QueuedToken(tag_span, QueuedTokenType::Tag(handle, suffix)) =
1802 self.fetch_token()
1803 else {
1804 unreachable!("tag token disappeared after peek")
1805 };
1806 tag_start = Some(tag_span.start);
1807 tag = Some(self.resolve_tag(tag_span, &handle, suffix)?);
1808 property_end = Some(tag_span.end);
1809 }
1810 if let Some(comment) = self.maybe_next_comment_event()? {
1811 self.save_pending_node_properties(anchor_id, tag, tag_start, property_end);
1812 return Ok(comment);
1813 }
1814 }
1815 QueuedToken(mark, QueuedTokenType::Tag(..)) if tag.is_none() => {
1816 let QueuedTokenType::Tag(handle, suffix) = self.fetch_token().1 else {
1817 unreachable!("tag token disappeared after peek")
1818 };
1819 tag_start = Some(mark.start);
1820 property_end = Some(mark.end);
1821 tag = Some(self.resolve_tag(mark, &handle, suffix)?);
1822 if anchor_id == 0 {
1823 if let QueuedTokenType::Anchor(_) = &self.peek_token()?.1 {
1824 let QueuedToken(mark, QueuedTokenType::Anchor(name)) = self.fetch_token()
1825 else {
1826 unreachable!("anchor token disappeared after peek")
1827 };
1828 anchor_id = self.register_anchor(name, &mark)?;
1829 property_end = Some(mark.end);
1830 }
1831 }
1832 if let Some(comment) = self.maybe_next_comment_event()? {
1833 self.save_pending_node_properties(anchor_id, tag, tag_start, property_end);
1834 return Ok(comment);
1835 }
1836 }
1837 _ => {}
1838 }
1839 match *self.peek_token()? {
1840 QueuedToken(mark, QueuedTokenType::BlockEntry) if indentless_sequence => {
1841 self.start_block_collection(mark.start)?;
1842 self.skip();
1843 let start = (
1844 Event::SequenceStart(StructureStyle::Block, anchor_id, tag),
1845 mark.with_tag_start(tag_start),
1846 );
1847 let comments = match self.next_comment_events() {
1848 Ok(comments) => comments,
1849 Err(error) if !matches!(error.kind(), ErrorKind::TooManyComments) => {
1850 debug_assert!(self.deferred_error.is_none());
1855 self.deferred_error = Some(error);
1856 self.pending_empty_scalar_span = Some(mark);
1857 self.state = State::IndentlessSequenceEntryNode;
1858 return Ok(start);
1859 }
1860 Err(error) => return Err(error),
1861 };
1862 if comments.is_empty() {
1863 self.pending_empty_scalar_span = Some(mark);
1864 self.state = State::IndentlessSequenceEntryNode;
1865 Ok(start)
1866 } else if let Ok(QueuedToken(
1867 _,
1868 QueuedTokenType::BlockEntry
1869 | QueuedTokenType::Key
1870 | QueuedTokenType::Value
1871 | QueuedTokenType::BlockEnd,
1872 )) = self.peek_token()
1873 {
1874 self.state = State::IndentlessSequenceEntry;
1875 Ok(self.queue_two_events_by_span(
1876 comments,
1877 start,
1878 (Event::empty_scalar(), mark),
1879 ))
1880 } else {
1881 self.pending_empty_scalar_span = Some(mark);
1882 self.state = State::IndentlessSequenceEntryNode;
1883 Ok(self.queue_event_by_span(comments, start))
1884 }
1885 }
1886 QueuedToken(_, QueuedTokenType::Scalar(..)) => {
1887 self.pop_state();
1888 let QueuedToken(mark, QueuedTokenType::Scalar(style, v)) = self.fetch_token()
1889 else {
1890 unreachable!("scalar token disappeared after peek")
1891 };
1892 Ok(Self::attach_tag_start(
1893 Event::Scalar(v, style, anchor_id, tag),
1894 mark,
1895 tag_start,
1896 ))
1897 }
1898 QueuedToken(mark, QueuedTokenType::FlowSequenceStart) => {
1899 self.state = State::FlowSequenceFirstEntry;
1900 self.skip();
1901 Ok(Self::attach_tag_start(
1902 Event::SequenceStart(StructureStyle::Flow, anchor_id, tag),
1903 mark,
1904 tag_start,
1905 ))
1906 }
1907 QueuedToken(mark, QueuedTokenType::FlowMappingStart) => {
1908 self.state = State::FlowMappingFirstKey;
1909 self.skip();
1910 Ok(Self::attach_tag_start(
1911 Event::MappingStart(StructureStyle::Flow, anchor_id, tag),
1912 mark,
1913 tag_start,
1914 ))
1915 }
1916 QueuedToken(mark, QueuedTokenType::BlockSequenceStart) if block => {
1917 self.start_block_collection(mark.start)?;
1918 self.state = State::BlockSequenceFirstEntry;
1919 self.skip();
1920 Ok(Self::attach_tag_start(
1921 Event::SequenceStart(StructureStyle::Block, anchor_id, tag),
1922 mark,
1923 tag_start,
1924 ))
1925 }
1926 QueuedToken(mark, QueuedTokenType::BlockMappingStart) if block => {
1927 self.start_block_collection(mark.start)?;
1928 self.state = State::BlockMappingFirstKey;
1929 self.skip();
1930 Ok(Self::attach_tag_start(
1931 Event::MappingStart(StructureStyle::Block, anchor_id, tag),
1932 mark,
1933 tag_start,
1934 ))
1935 }
1936 QueuedToken(mark, _) if tag.is_some() || anchor_id > 0 => {
1938 self.pop_state();
1939 let span = property_end.map_or_else(|| Span::empty(mark.start), Span::empty);
1940 Ok(Self::attach_tag_start(
1941 Event::empty_scalar_with_anchor(anchor_id, tag),
1942 span,
1943 tag_start,
1944 ))
1945 }
1946 QueuedToken(span, _) => {
1947 let kind = match self.state {
1948 State::FlowSequenceFirstEntry | State::FlowSequenceEntry => {
1949 ErrorKind::UnexpectedEofFlowSequence
1950 }
1951 State::FlowMappingFirstKey
1952 | State::FlowMappingKey
1953 | State::FlowMappingValue
1954 | State::FlowMappingEmptyValue => ErrorKind::UnexpectedEofFlowMapping,
1955 State::FlowSequenceEntryMappingKey
1956 | State::FlowSequenceEntryMappingValue
1957 | State::FlowSequenceEntryMappingEnd
1958 | State::FlowNode => ErrorKind::UnexpectedEofImplicitFlowMapping,
1959 State::BlockSequenceFirstEntry
1960 | State::BlockSequenceEntry
1961 | State::BlockNode => ErrorKind::UnexpectedEofBlockSequence,
1962 State::BlockMappingFirstKey
1963 | State::BlockMappingKey
1964 | State::BlockMappingValue
1965 | State::BlockNodeOrIndentlessSequence => ErrorKind::UnexpectedEofBlockMapping,
1966 _ => ErrorKind::ExpectedNodeContent,
1967 };
1968 Err(ScanError::from_kind(span.start, kind))
1969 }
1970 }
1971 }
1972
1973 fn block_mapping_key<'a>(&mut self, _first: bool) -> ParseResult<'a>
1974 where
1975 'input: 'a,
1976 {
1977 match *self.peek_token()? {
1978 QueuedToken(_, QueuedTokenType::Key) => {
1979 if let QueuedToken(key_span, QueuedTokenType::Key) = *self.peek_token()? {
1981 self.pending_key_indent = Some(key_span.start.col());
1982 }
1983 self.skip();
1984 if let Some(comment) = self.maybe_next_comment_event()? {
1985 self.state = State::BlockMappingKeyNode;
1986 Ok(comment)
1987 } else {
1988 self.block_mapping_key_node()
1989 }
1990 }
1991 QueuedToken(mark, QueuedTokenType::Value) => {
1993 self.state = State::BlockMappingValue;
1994 Ok((Event::empty_scalar(), Span::empty(mark.start)))
1995 }
1996 QueuedToken(mark, QueuedTokenType::BlockEnd) => {
1997 self.end_block_collection();
1998 self.pop_state();
1999 self.skip();
2000 Ok((Event::MappingEnd, mark))
2001 }
2002 QueuedToken(span, _) => Err(ScanError::from_kind(
2003 span.start,
2004 ErrorKind::ExpectedBlockMappingKey,
2005 )),
2006 }
2007 }
2008
2009 fn block_mapping_key_node<'a>(&mut self) -> ParseResult<'a>
2010 where
2011 'input: 'a,
2012 {
2013 if let QueuedToken(
2014 mark,
2015 QueuedTokenType::Key | QueuedTokenType::Value | QueuedTokenType::BlockEnd,
2016 ) = *self.peek_token()?
2017 {
2018 self.state = State::BlockMappingValue;
2019 Ok((Event::empty_scalar(), Span::empty(mark.start)))
2020 } else {
2021 self.defer_parse_node(
2022 State::BlockNodeOrIndentlessSequence,
2023 State::BlockMappingValue,
2024 true,
2025 true,
2026 )
2027 }
2028 }
2029
2030 fn block_mapping_value<'a>(&mut self) -> ParseResult<'a>
2031 where
2032 'input: 'a,
2033 {
2034 match *self.peek_token()? {
2035 QueuedToken(mark, QueuedTokenType::Value) => {
2036 self.skip();
2037 let comments = self.next_comment_events()?;
2038 if comments.is_empty() {
2039 self.block_mapping_value_node_with_empty_span(mark)
2040 } else if let Ok(QueuedToken(
2041 _,
2042 QueuedTokenType::Key | QueuedTokenType::Value | QueuedTokenType::BlockEnd,
2043 )) = self.peek_token()
2044 {
2045 self.state = State::BlockMappingKey;
2046 Ok(self.queue_event_by_span(comments, (Event::empty_scalar(), mark)))
2047 } else {
2048 self.pending_empty_scalar_span = Some(mark);
2049 self.state = State::BlockMappingValueNode;
2050 Ok(self.queue_tail_and_return_first(comments))
2051 }
2052 }
2053 QueuedToken(mark, _) => {
2054 self.state = State::BlockMappingKey;
2055 Ok((Event::empty_scalar(), Span::empty(mark.start)))
2056 }
2057 }
2058 }
2059
2060 fn block_mapping_value_node<'a>(&mut self) -> ParseResult<'a>
2061 where
2062 'input: 'a,
2063 {
2064 let Some(mark) = self.pending_empty_scalar_span.take() else {
2065 unreachable!(
2066 "block mapping value-node state entered without a pending empty-scalar span"
2067 )
2068 };
2069 self.block_mapping_value_node_with_empty_span(mark)
2070 }
2071
2072 fn block_mapping_value_node_with_empty_span<'a>(&mut self, mark: Span) -> ParseResult<'a>
2073 where
2074 'input: 'a,
2075 {
2076 if let QueuedToken(
2077 _,
2078 QueuedTokenType::Key | QueuedTokenType::Value | QueuedTokenType::BlockEnd,
2079 ) = *self.peek_token()?
2080 {
2081 self.state = State::BlockMappingKey;
2082 Ok((Event::empty_scalar(), mark))
2083 } else {
2084 self.defer_parse_node(
2085 State::BlockNodeOrIndentlessSequence,
2086 State::BlockMappingKey,
2087 true,
2088 true,
2089 )
2090 }
2091 }
2092
2093 fn flow_mapping_key<'a>(&mut self, first: bool) -> ParseResult<'a>
2094 where
2095 'input: 'a,
2096 {
2097 let span: Span =
2098 if let QueuedToken(mark, QueuedTokenType::FlowMappingEnd) = *self.peek_token()? {
2099 mark
2100 } else {
2101 if !first {
2102 match *self.peek_token()? {
2103 QueuedToken(_, QueuedTokenType::FlowEntry) => {
2104 self.skip();
2105 if let Some(comment) = self.maybe_next_comment_event()? {
2106 self.state = State::FlowMappingFirstKey;
2107 return Ok(comment);
2108 }
2109 }
2110 QueuedToken(span, _) => {
2111 return Err(ScanError::from_kind(
2112 span.start,
2113 ErrorKind::ExpectedFlowMappingSeparator,
2114 ))
2115 }
2116 }
2117 }
2118
2119 match *self.peek_token()? {
2120 QueuedToken(_, QueuedTokenType::Key) => {
2121 self.skip();
2122 if let Some(comment) = self.maybe_next_comment_event()? {
2123 self.state = State::FlowMappingKeyNode;
2124 return Ok(comment);
2125 }
2126 return self.flow_mapping_key_node();
2127 }
2128 QueuedToken(marker, QueuedTokenType::Value) => {
2129 self.state = State::FlowMappingValue;
2130 return Ok((Event::empty_scalar(), Span::empty(marker.start)));
2131 }
2132 QueuedToken(_, QueuedTokenType::FlowMappingEnd) => (),
2133 _ => {
2134 return self.defer_parse_node(
2135 State::FlowNode,
2136 State::FlowMappingEmptyValue,
2137 false,
2138 false,
2139 );
2140 }
2141 }
2142
2143 self.peek_token()?.0
2144 };
2145
2146 self.pop_state();
2147 self.skip();
2148 Ok((Event::MappingEnd, span))
2149 }
2150
2151 fn flow_mapping_key_node<'a>(&mut self) -> ParseResult<'a>
2152 where
2153 'input: 'a,
2154 {
2155 if let QueuedToken(
2156 mark,
2157 QueuedTokenType::Value | QueuedTokenType::FlowEntry | QueuedTokenType::FlowMappingEnd,
2158 ) = *self.peek_token()?
2159 {
2160 self.state = State::FlowMappingValue;
2161 Ok((Event::empty_scalar(), Span::empty(mark.start)))
2162 } else {
2163 self.defer_parse_node(State::FlowNode, State::FlowMappingValue, false, false)
2164 }
2165 }
2166
2167 fn flow_mapping_value<'a>(&mut self, empty: bool) -> ParseResult<'a>
2168 where
2169 'input: 'a,
2170 {
2171 let span: Span = {
2172 if empty {
2173 let QueuedToken(mark, _) = *self.peek_token()?;
2174 self.state = State::FlowMappingKey;
2175 return Ok((Event::empty_scalar(), Span::empty(mark.start)));
2176 }
2177 match *self.peek_token()? {
2178 QueuedToken(span, QueuedTokenType::Value) => {
2179 self.skip();
2180 let comments = self.next_comment_events()?;
2181 if comments.is_empty() {
2182 return self.flow_mapping_value_node_with_empty_span(span);
2183 }
2184 if let Ok(QueuedToken(
2185 _,
2186 QueuedTokenType::FlowEntry | QueuedTokenType::FlowMappingEnd,
2187 )) = self.peek_token()
2188 {
2189 self.state = State::FlowMappingKey;
2190 return Ok(
2191 self.queue_event_by_span(comments, (Event::empty_scalar(), span))
2192 );
2193 }
2194
2195 self.pending_empty_scalar_span = Some(span);
2196 self.state = State::FlowMappingValueNode;
2197 return Ok(self.queue_tail_and_return_first(comments));
2198 }
2199 QueuedToken(marker, _) => Span::empty(marker.start),
2200 }
2201 };
2202
2203 self.state = State::FlowMappingKey;
2204 Ok((Event::empty_scalar(), span))
2205 }
2206
2207 fn flow_mapping_value_node<'a>(&mut self) -> ParseResult<'a>
2208 where
2209 'input: 'a,
2210 {
2211 let Some(mark) = self.pending_empty_scalar_span.take() else {
2212 unreachable!(
2213 "flow mapping value-node state entered without a pending empty-scalar span"
2214 )
2215 };
2216 self.flow_mapping_value_node_with_empty_span(mark)
2217 }
2218
2219 fn flow_mapping_value_node_with_empty_span<'a>(&mut self, mark: Span) -> ParseResult<'a>
2220 where
2221 'input: 'a,
2222 {
2223 match self.peek_token()?.1 {
2224 QueuedTokenType::FlowEntry | QueuedTokenType::FlowMappingEnd => {
2225 self.state = State::FlowMappingKey;
2226 Ok((Event::empty_scalar(), mark))
2227 }
2228 _ => self.defer_parse_node(State::FlowNode, State::FlowMappingKey, false, false),
2229 }
2230 }
2231
2232 fn flow_sequence_entry<'a>(&mut self, first: bool) -> ParseResult<'a>
2233 where
2234 'input: 'a,
2235 {
2236 match *self.peek_token()? {
2237 QueuedToken(mark, QueuedTokenType::FlowSequenceEnd) => {
2238 self.pop_state();
2239 self.skip();
2240 return Ok((Event::SequenceEnd, mark));
2241 }
2242 QueuedToken(_, QueuedTokenType::FlowEntry) if !first => {
2243 self.skip();
2244 if let Some(comment) = self.maybe_next_comment_event()? {
2245 self.state = State::FlowSequenceFirstEntry;
2246 return Ok(comment);
2247 }
2248 }
2249 QueuedToken(span, _) if !first => {
2250 return Err(ScanError::from_kind(
2251 span.start,
2252 ErrorKind::ExpectedFlowSequenceSeparator,
2253 ));
2254 }
2255 _ => { }
2256 }
2257 match *self.peek_token()? {
2258 QueuedToken(mark, QueuedTokenType::FlowSequenceEnd) => {
2259 self.pop_state();
2260 self.skip();
2261 Ok((Event::SequenceEnd, mark))
2262 }
2263 QueuedToken(mark, QueuedTokenType::Key) => {
2264 self.state = State::FlowSequenceEntryMappingKey;
2265 self.skip();
2266 Ok((Event::MappingStart(StructureStyle::Flow, 0, None), mark))
2267 }
2268 _ => self.defer_parse_node(State::FlowNode, State::FlowSequenceEntry, false, false),
2269 }
2270 }
2271
2272 fn indentless_sequence_entry<'a>(&mut self) -> ParseResult<'a>
2273 where
2274 'input: 'a,
2275 {
2276 match *self.peek_token()? {
2277 QueuedToken(mark, QueuedTokenType::BlockEntry) => {
2278 self.skip();
2279 let comments = self.next_comment_events()?;
2280 if comments.is_empty() {
2281 self.indentless_sequence_entry_node_with_empty_span(mark)
2282 } else if let Ok(QueuedToken(
2283 _,
2284 QueuedTokenType::BlockEntry
2285 | QueuedTokenType::Key
2286 | QueuedTokenType::Value
2287 | QueuedTokenType::BlockEnd,
2288 )) = self.peek_token()
2289 {
2290 self.state = State::IndentlessSequenceEntry;
2291 Ok(self.queue_event_by_span(comments, (Event::empty_scalar(), mark)))
2292 } else {
2293 self.pending_empty_scalar_span = Some(mark);
2294 self.state = State::IndentlessSequenceEntryNode;
2295 Ok(self.queue_tail_and_return_first(comments))
2296 }
2297 }
2298 QueuedToken(mark, _) => {
2299 self.end_block_collection();
2300 self.pop_state();
2301 Ok((Event::SequenceEnd, mark))
2302 }
2303 }
2304 }
2305
2306 fn indentless_sequence_entry_node<'a>(&mut self) -> ParseResult<'a>
2307 where
2308 'input: 'a,
2309 {
2310 let Some(mark) = self.pending_empty_scalar_span.take() else {
2311 unreachable!(
2312 "indentless sequence entry-node state entered without a pending empty-scalar span"
2313 )
2314 };
2315 self.indentless_sequence_entry_node_with_empty_span(mark)
2316 }
2317
2318 fn indentless_sequence_entry_node_with_empty_span<'a>(&mut self, mark: Span) -> ParseResult<'a>
2319 where
2320 'input: 'a,
2321 {
2322 if let QueuedToken(
2323 _,
2324 QueuedTokenType::BlockEntry
2325 | QueuedTokenType::Key
2326 | QueuedTokenType::Value
2327 | QueuedTokenType::BlockEnd,
2328 ) = *self.peek_token()?
2329 {
2330 self.state = State::IndentlessSequenceEntry;
2331 Ok((Event::empty_scalar(), mark))
2332 } else {
2333 self.defer_parse_node(
2334 State::BlockNode,
2335 State::IndentlessSequenceEntry,
2336 true,
2337 false,
2338 )
2339 }
2340 }
2341
2342 fn block_sequence_entry<'a>(&mut self, _first: bool) -> ParseResult<'a>
2343 where
2344 'input: 'a,
2345 {
2346 match *self.peek_token()? {
2347 QueuedToken(mark, QueuedTokenType::BlockEnd) => {
2348 self.end_block_collection();
2349 self.pop_state();
2350 self.skip();
2351 Ok((Event::SequenceEnd, mark))
2352 }
2353 QueuedToken(mark, QueuedTokenType::BlockEntry) => {
2354 self.skip();
2355 let comments = self.next_comment_events()?;
2356 if comments.is_empty() {
2357 self.block_sequence_entry_node_with_empty_span(mark)
2358 } else if let Ok(QueuedToken(
2359 _,
2360 QueuedTokenType::BlockEntry | QueuedTokenType::BlockEnd,
2361 )) = self.peek_token()
2362 {
2363 self.state = State::BlockSequenceEntry;
2364 Ok(self.queue_event_by_span(comments, (Event::empty_scalar(), mark)))
2365 } else {
2366 self.pending_empty_scalar_span = Some(mark);
2367 self.state = State::BlockSequenceEntryNode;
2368 Ok(self.queue_tail_and_return_first(comments))
2369 }
2370 }
2371 QueuedToken(span, _) => Err(ScanError::from_kind(
2372 span.start,
2373 ErrorKind::ExpectedBlockSequenceEntry,
2374 )),
2375 }
2376 }
2377
2378 fn block_sequence_entry_node<'a>(&mut self) -> ParseResult<'a>
2379 where
2380 'input: 'a,
2381 {
2382 let Some(mark) = self.pending_empty_scalar_span.take() else {
2383 unreachable!(
2384 "block sequence entry-node state entered without a pending empty-scalar span"
2385 )
2386 };
2387 self.block_sequence_entry_node_with_empty_span(mark)
2388 }
2389
2390 fn block_sequence_entry_node_with_empty_span<'a>(&mut self, mark: Span) -> ParseResult<'a>
2391 where
2392 'input: 'a,
2393 {
2394 if let QueuedToken(_, QueuedTokenType::BlockEntry | QueuedTokenType::BlockEnd) =
2395 *self.peek_token()?
2396 {
2397 self.state = State::BlockSequenceEntry;
2398 Ok((Event::empty_scalar(), mark))
2399 } else {
2400 self.defer_parse_node(State::BlockNode, State::BlockSequenceEntry, true, false)
2401 }
2402 }
2403
2404 fn flow_sequence_entry_mapping_key<'a>(&mut self) -> ParseResult<'a>
2405 where
2406 'input: 'a,
2407 {
2408 if let QueuedToken(mark, QueuedTokenType::FlowEntry | QueuedTokenType::FlowSequenceEnd) =
2409 *self.peek_token()?
2410 {
2411 self.state = State::FlowSequenceEntryMappingValue;
2412 Ok((Event::empty_scalar(), Span::empty(mark.start)))
2413 } else {
2414 self.defer_parse_node(
2415 State::FlowNode,
2416 State::FlowSequenceEntryMappingValue,
2417 false,
2418 false,
2419 )
2420 }
2421 }
2422
2423 fn flow_sequence_entry_mapping_value<'a>(&mut self) -> ParseResult<'a>
2424 where
2425 'input: 'a,
2426 {
2427 match *self.peek_token()? {
2428 QueuedToken(_, QueuedTokenType::Value) => {
2429 self.skip();
2430 if let Some(comment) = self.maybe_next_comment_event()? {
2431 self.state = State::FlowSequenceEntryMappingValueNode;
2432 Ok(comment)
2433 } else {
2434 self.flow_sequence_entry_mapping_value_node()
2435 }
2436 }
2437 QueuedToken(mark, _) => {
2438 self.state = State::FlowSequenceEntryMappingEnd;
2439 Ok((Event::empty_scalar(), Span::empty(mark.start)))
2440 }
2441 }
2442 }
2443
2444 fn flow_sequence_entry_mapping_value_node<'a>(&mut self) -> ParseResult<'a>
2445 where
2446 'input: 'a,
2447 {
2448 let QueuedToken(span, ref tok) = *self.peek_token()?;
2449 if matches!(
2450 tok,
2451 QueuedTokenType::FlowEntry | QueuedTokenType::FlowSequenceEnd
2452 ) {
2453 self.state = State::FlowSequenceEntryMappingEnd;
2454 Ok((Event::empty_scalar(), Span::empty(span.start)))
2455 } else {
2456 self.defer_parse_node(
2457 State::FlowNode,
2458 State::FlowSequenceEntryMappingEnd,
2459 false,
2460 false,
2461 )
2462 }
2463 }
2464
2465 #[allow(clippy::unnecessary_wraps)]
2466 fn flow_sequence_entry_mapping_end<'a>(&mut self) -> ParseResult<'a>
2467 where
2468 'input: 'a,
2469 {
2470 self.state = State::FlowSequenceEntry;
2471 let QueuedToken(span, _) = *self.peek_token()?;
2472 Ok((Event::MappingEnd, Span::empty(span.start)))
2473 }
2474
2475 fn resolve_tag(
2477 &self,
2478 span: Span,
2479 handle: &Cow<'input, str>,
2480 suffix: Cow<'input, str>,
2481 ) -> Result<Cow<'input, Tag>, ScanError> {
2482 let original_handle = handle.to_string();
2483 let suffix = suffix.into_owned();
2484 let tag = if handle == "!!" {
2485 Tag::with_original_handle(
2488 self.tags
2489 .get("!!")
2490 .map_or_else(|| "tag:yaml.org,2002:".to_string(), ToString::to_string),
2491 suffix,
2492 original_handle,
2493 )
2494 } else if handle.is_empty() && suffix == "!" {
2495 match self.tags.get("!") {
2497 Some(prefix) => {
2498 Tag::with_original_handle(prefix.to_string(), suffix, original_handle)
2499 }
2500 None => Tag::with_original_handle(String::new(), suffix, original_handle),
2501 }
2502 } else {
2503 let prefix = self.tags.get(&**handle);
2505 if let Some(prefix) = prefix {
2506 Tag::with_original_handle(prefix.to_string(), suffix, original_handle)
2507 } else {
2508 if handle.len() >= 2 && handle.starts_with('!') && handle.ends_with('!') {
2513 return Err(ScanError::from_kind(
2514 span.start,
2515 ErrorKind::UndeclaredTagHandle,
2516 ));
2517 }
2518 Tag::with_original_handle(handle.to_string(), suffix, original_handle)
2519 }
2520 };
2521 Ok(Cow::Owned(tag))
2522 }
2523}
2524
2525impl<'input, T: BorrowedInput<'input>> ParserTrait<'input> for Parser<'input, T> {
2526 fn peek(&mut self) -> Option<Result<&(Event<'input>, Span), ScanError>> {
2527 if let Some(ref x) = self.current {
2528 Some(Ok(x))
2529 } else if let Some(error) = &self.current_error {
2530 Some(Err(error.clone()))
2531 } else {
2532 if self.stream_end_emitted {
2533 return None;
2534 }
2535 match self.next_event_impl() {
2536 Ok(token) => self.current = Some(token),
2537 Err(error) => {
2538 self.current_error = Some(error.clone());
2539 return Some(Err(error));
2540 }
2541 }
2542 self.current.as_ref().map(Ok)
2543 }
2544 }
2545
2546 fn next_event(&mut self) -> Option<ParseResult<'input>> {
2547 if let Some(error) = self.current_error.take() {
2548 self.stream_end_emitted = true;
2549 return Some(Err(error));
2550 }
2551
2552 if self.stream_end_emitted {
2553 return None;
2554 }
2555
2556 let tok = self.next_event_impl();
2557 if matches!(tok, Ok((Event::StreamEnd, _)) | Err(_)) {
2558 self.stream_end_emitted = true;
2559 }
2560 Some(tok)
2561 }
2562
2563 fn load<R: SpannedEventReceiver<'input>>(
2564 &mut self,
2565 recv: &mut R,
2566 multi: bool,
2567 ) -> Result<(), ScanError> {
2568 let mut recv = InfallibleSpannedReceiver(recv);
2569 into_scan_result(ParserTrait::try_load(self, &mut recv, multi))
2570 }
2571
2572 fn try_load<R: TrySpannedEventReceiver<'input>>(
2573 &mut self,
2574 recv: &mut R,
2575 multi: bool,
2576 ) -> Result<(), TryLoadError<R::Error>> {
2577 let stream_start_buffered = matches!(self.current.as_ref(), Some((Event::StreamStart, _)));
2578 if !self.scanner.stream_started() || stream_start_buffered {
2579 let (ev, span) = self.next_event_impl()?;
2580 if ev != Event::StreamStart {
2581 return Err(TryLoadError::scan(ScanError::from_kind(
2582 span.start,
2583 ErrorKind::ExpectedStreamStart,
2584 )));
2585 }
2586 try_emit(recv, ev, span)?;
2587 }
2588
2589 let has_buffered_result = self.current.is_some()
2590 || self.current_error.is_some()
2591 || self.deferred_error.is_some()
2592 || !self.queued_events.is_empty();
2593 if self.scanner.stream_ended() && !has_buffered_result {
2594 try_emit(recv, Event::StreamEnd, Span::empty(self.scanner.mark()))?;
2597 self.stream_end_emitted = true;
2598 return Ok(());
2599 }
2600
2601 loop {
2602 let (ev, span) = if let Some(error) = self.current_error.take() {
2603 self.stream_end_emitted = true;
2604 return Err(TryLoadError::scan(error));
2605 } else {
2606 self.next_event_impl()?
2607 };
2608 let is_doc_end = matches!(ev, Event::DocumentEnd);
2609 let is_stream_end = matches!(ev, Event::StreamEnd);
2610
2611 try_emit(recv, ev, span)?;
2612
2613 if is_stream_end {
2614 self.stream_end_emitted = true;
2615 return Ok(());
2616 }
2617 if !multi && is_doc_end {
2618 return Ok(());
2619 }
2620 }
2621 }
2622}
2623
2624impl<'input, T: BorrowedInput<'input>> Iterator for Parser<'input, T> {
2625 type Item = Result<(Event<'input>, Span), ScanError>;
2626
2627 fn next(&mut self) -> Option<Self::Item> {
2628 self.next_event()
2629 }
2630}
2631
2632impl<'input, T: BorrowedInput<'input>> core::iter::FusedIterator for Parser<'input, T> {}
2633
2634#[cfg(test)]
2635mod test {
2636 use alloc::{borrow::Cow, string::ToString, vec, vec::Vec};
2637 #[cfg(feature = "error_messages")]
2638 use alloc::{format, string::String};
2639 #[cfg(feature = "error_messages")]
2640 use core::{error::Error as _, fmt};
2641
2642 #[cfg(feature = "error_messages")]
2643 use crate::error::{ErrorKind, ScanError};
2644 use crate::scanner::{Marker, ScalarStyle, Span};
2645
2646 use super::{
2647 Event, EventReceiver, Parser, State, StructureStyle, Tag, TryEventReceiver, TryLoadError,
2648 TrySpannedEventReceiver, YamlVersion,
2649 };
2650
2651 #[derive(Default)]
2652 struct CollectingSink<'input> {
2653 events: Vec<Event<'input>>,
2654 }
2655
2656 impl<'input> EventReceiver<'input> for CollectingSink<'input> {
2657 fn on_event(&mut self, ev: Event<'input>) {
2658 self.events.push(ev);
2659 }
2660 }
2661
2662 #[cfg(feature = "error_messages")]
2663 fn first_error_info(input: &str) -> String {
2664 for event in Parser::new_from_str(input) {
2665 if let Err(err) = event {
2666 return err.info();
2667 }
2668 }
2669 panic!("expected parser error")
2670 }
2671
2672 fn first_tagged_scalar_tag(input: &str) -> Tag {
2673 Parser::new_from_str(input)
2674 .find_map(|event| match event.expect("input should parse").0 {
2675 Event::Scalar(_, _, _, Some(tag)) => Some(tag.into_owned()),
2676 _ => None,
2677 })
2678 .expect("expected tagged scalar")
2679 }
2680
2681 #[test]
2682 fn deferred_parse_node_can_emit_comment_before_flow_node() {
2683 let mut parser = Parser::new_from_str("---\n# deferred\nvalue\n");
2684 assert_eq!(parser.stream_start().unwrap().0, Event::StreamStart);
2685 assert_eq!(
2686 parser.document_start(true).unwrap().0,
2687 Event::DocumentStart(true, None)
2688 );
2689
2690 let (event, _) = parser
2691 .defer_parse_node(State::FlowNode, State::FlowMappingKey, false, false)
2692 .unwrap();
2693
2694 assert!(matches!(event, Event::Comment(text, _) if text == " deferred"));
2695 assert_eq!(parser.state, State::FlowNode);
2696 }
2697
2698 #[test]
2699 fn queued_node_event_gets_pending_key_indent() {
2700 let mut parser = Parser::new_from_str("");
2701 let span = Span::empty(Marker::new(0, 1, 0));
2702
2703 parser.pending_key_indent = Some(3);
2704 parser
2705 .queued_events
2706 .push_back((Event::SequenceStart(StructureStyle::Block, 0, None), span));
2707
2708 let (event, span) = parser.next_event_impl().unwrap();
2709
2710 assert!(matches!(
2711 event,
2712 Event::SequenceStart(StructureStyle::Block, 0, None)
2713 ));
2714 assert_eq!(span.indent, Some(3));
2715 assert_eq!(parser.pending_key_indent, None);
2716 }
2717
2718 #[test]
2719 fn state_machine_handles_deferred_flow_node_states() {
2720 let mut parser = Parser::new_from_str("value\n");
2721 assert_eq!(parser.stream_start().unwrap().0, Event::StreamStart);
2722 assert_eq!(
2723 parser.document_start(true).unwrap().0,
2724 Event::DocumentStart(false, None)
2725 );
2726 parser.state = State::FlowNode;
2727 parser.push_state(State::End);
2728
2729 let (event, _) = parser.state_machine().unwrap();
2730
2731 assert!(matches!(event, Event::Scalar(value, ..) if value == "value"));
2732
2733 let mut parser = Parser::new_from_str("value\n");
2734 assert_eq!(parser.stream_start().unwrap().0, Event::StreamStart);
2735 assert_eq!(
2736 parser.document_start(true).unwrap().0,
2737 Event::DocumentStart(false, None)
2738 );
2739 parser.state = State::FlowSequenceEntryMappingValueNode;
2740
2741 let (event, _) = parser.state_machine().unwrap();
2742
2743 assert!(matches!(event, Event::Scalar(value, ..) if value == "value"));
2744 }
2745
2746 #[test]
2747 fn display_resolved_core_tag_without_extra_bang() {
2748 let tag = Tag::with_original_handle("tag:yaml.org,2002:", "str", "!!");
2749
2750 assert_eq!(tag.to_string(), "tag:yaml.org,2002:str");
2751 }
2752
2753 #[test]
2754 fn tag_helpers_distinguish_core_and_local_tags() {
2755 let core = Tag::with_original_handle("tag:yaml.org,2002:", "int", "!!");
2756 let local = Tag::new("!", "thing");
2757 let non_specific = Tag::with_original_handle("", "!", "");
2758 let verbatim = Tag::with_original_handle("", "tag:example.com,2000:thing", "");
2759 let unknown_yaml_org = Tag::with_original_handle("", "tag:yaml.org,2002:application", "");
2760
2761 assert_eq!(core.core_suffix(), Some("int"));
2762 assert!(core.is_yaml_core_schema());
2763 assert!(core.is_yaml_core_schema_tag("int"));
2764 assert!(!core.is_yaml_core_schema_tag("str"));
2765 assert!(!core.is_custom());
2766 assert_eq!(core.parts(), ("tag:yaml.org,2002:", "int"));
2767 assert_eq!(core.original_parts(), ("!!", "int"));
2768 assert_eq!(core.original(), "!!int");
2769
2770 assert_eq!(local.core_suffix(), None);
2771 assert!(!local.is_yaml_core_schema());
2772 assert!(!local.is_yaml_core_schema_tag("thing"));
2773 assert!(local.is_custom());
2774 assert_eq!(local.parts(), ("!", "thing"));
2775 assert_eq!(local.original_parts(), ("!", "thing"));
2776 assert_eq!(local.original(), "!thing");
2777 assert_eq!(local.to_string(), "!thing");
2778
2779 assert_eq!(non_specific.parts(), ("", "!"));
2780 assert_eq!(non_specific.original_parts(), ("", "!"));
2781 assert_eq!(non_specific.original(), "!");
2782
2783 assert_eq!(verbatim.parts(), ("", "tag:example.com,2000:thing"));
2784 assert_eq!(
2785 verbatim.original_parts(),
2786 ("", "tag:example.com,2000:thing")
2787 );
2788 assert_eq!(verbatim.original(), "!<tag:example.com,2000:thing>");
2789
2790 assert_eq!(unknown_yaml_org.core_suffix(), None);
2791 assert!(!unknown_yaml_org.is_yaml_core_schema());
2792 assert!(unknown_yaml_org.is_custom());
2793 }
2794
2795 #[test]
2796 fn core_suffix_uses_resolved_tag_uri_for_common_spellings() {
2797 let cases = [
2798 ("shorthand", "v: !!int 1\n", ("tag:yaml.org,2002:", "int")),
2799 (
2800 "verbatim",
2801 "v: !<tag:yaml.org,2002:int> 1\n",
2802 ("", "tag:yaml.org,2002:int"),
2803 ),
2804 (
2805 "full prefix",
2806 "%TAG !e! tag:yaml.org,2002:\n---\nv: !e!int 1\n",
2807 ("tag:yaml.org,2002:", "int"),
2808 ),
2809 (
2810 "mid-split",
2811 "%TAG !m! tag:yaml.org,2002:i\n---\nv: !m!nt 1\n",
2812 ("tag:yaml.org,2002:i", "nt"),
2813 ),
2814 ];
2815
2816 for (label, input, expected_parts) in cases {
2817 let tag = first_tagged_scalar_tag(input);
2818
2819 assert_eq!(tag.parts(), expected_parts, "{label}");
2820 assert_eq!(tag.core_suffix(), Some("int"), "{label}");
2821 assert!(tag.is_yaml_core_schema(), "{label}");
2822 assert!(tag.is_yaml_core_schema_tag("int"), "{label}");
2823 assert!(!tag.is_yaml_core_schema_tag("str"), "{label}");
2824 assert!(!tag.is_custom(), "{label}");
2825 }
2826 }
2827
2828 #[test]
2829 fn core_suffix_rejects_non_core_yaml_org_tags() {
2830 let cases = [
2831 "binary",
2832 "merge",
2833 "omap",
2834 "pairs",
2835 "set",
2836 "timestamp",
2837 "value",
2838 "yaml",
2839 ];
2840
2841 for suffix in cases {
2842 let tag = Tag::with_original_handle("tag:yaml.org,2002:", suffix, "!!");
2843
2844 assert_eq!(tag.core_suffix(), None, "{suffix}");
2845 assert!(!tag.is_yaml_core_schema(), "{suffix}");
2846 assert!(tag.is_custom(), "{suffix}");
2847 }
2848 }
2849
2850 #[test]
2851 fn core_suffix_rejects_non_core_tags() {
2852 let cases = [
2853 ("local", "v: !local 1\n"),
2854 ("verbatim custom", "v: !<tag:example.com,2000:int> 1\n"),
2855 (
2856 "custom directive",
2857 "%TAG !e! tag:example.com,2000:\n---\nv: !e!int 1\n",
2858 ),
2859 (
2860 "overridden secondary handle",
2861 "%TAG !! tag:example.com,2000:app/\n---\nv: !!int 1\n",
2862 ),
2863 ];
2864
2865 for (label, input) in cases {
2866 let tag = first_tagged_scalar_tag(input);
2867
2868 assert_eq!(tag.core_suffix(), None, "{label}");
2869 assert!(!tag.is_yaml_core_schema(), "{label}");
2870 assert!(!tag.is_yaml_core_schema_tag("int"), "{label}");
2871 assert!(tag.is_custom(), "{label}");
2872 }
2873 }
2874
2875 #[test]
2876 fn suffix_in_namespace_resolves_across_spellings() {
2877 const NS: &str = "tag:yaml.org,2002:";
2878
2879 let shorthand = Tag::with_original_handle(NS, "omap", "!!");
2884 let verbatim = Tag::with_original_handle("", "tag:yaml.org,2002:omap", "");
2885 let mid_split = Tag::with_original_handle("tag:yaml.org,2002:o", "map", "!o!");
2886 let inside_split = Tag::with_original_handle("tag:yaml.org,", "2002:omap", "!y!");
2887 for tag in [&shorthand, &verbatim, &mid_split, &inside_split] {
2888 assert_eq!(tag.suffix_in_namespace(NS).as_deref(), Some("omap"));
2889 assert_eq!(tag.core_suffix(), None);
2890 }
2891
2892 assert!(matches!(
2895 shorthand.suffix_in_namespace(NS),
2896 Some(Cow::Borrowed(_))
2897 ));
2898 assert!(matches!(
2899 verbatim.suffix_in_namespace(NS),
2900 Some(Cow::Borrowed(_))
2901 ));
2902 assert!(matches!(
2903 inside_split.suffix_in_namespace(NS),
2904 Some(Cow::Borrowed(_))
2905 ));
2906 assert!(matches!(
2907 mid_split.suffix_in_namespace(NS),
2908 Some(Cow::Owned(_))
2909 ));
2910
2911 let merge = Tag::with_original_handle(NS, "merge", "!!");
2914 assert_eq!(merge.suffix_in_namespace(NS).as_deref(), Some("merge"));
2915 assert_eq!(merge.core_suffix(), None);
2916 assert_eq!(
2917 Tag::new(NS, "int").suffix_in_namespace(NS).as_deref(),
2918 Some("int")
2919 );
2920
2921 assert_eq!(Tag::new("!", "omap").suffix_in_namespace(NS), None);
2923 assert_eq!(
2924 Tag::with_original_handle("", "tag:example.com,2000:omap", "").suffix_in_namespace(NS),
2925 None
2926 );
2927 }
2928
2929 #[test]
2930 fn attach_tag_start_applies_marker_to_span() {
2931 let event = Event::Scalar("value".into(), ScalarStyle::Plain, 0, None);
2932 let span = Span::new(Marker::new(6, 1, 6), Marker::new(11, 1, 11));
2933 let tag_start = Marker::new(0, 1, 0);
2934
2935 let (attached_event, attached_span) =
2936 Parser::<crate::input::str::StrInput<'_>>::attach_tag_start(
2937 event.clone(),
2938 span,
2939 Some(tag_start),
2940 );
2941
2942 assert_eq!(attached_event, event);
2943 assert_eq!(attached_span.start, span.start);
2944 assert_eq!(attached_span.end, span.end);
2945 assert_eq!(attached_span.tag_start(), Some(tag_start));
2946 }
2947
2948 #[test]
2949 fn event_inspection_helpers_report_node_metadata() {
2950 let tag = Tag::new("!", "thing");
2951 let scalar = Event::Scalar(
2952 "value".into(),
2953 ScalarStyle::DoubleQuoted,
2954 7,
2955 Some(Cow::Borrowed(&tag)),
2956 );
2957 let sequence =
2958 Event::SequenceStart(StructureStyle::Block, 8, Some(Cow::Owned(tag.clone())));
2959 let mapping = Event::MappingStart(StructureStyle::Block, 9, Some(Cow::Borrowed(&tag)));
2960
2961 assert_eq!(scalar.anchor_id(), Some(7));
2962 assert_eq!(scalar.alias_id(), None);
2963 assert_eq!(scalar.tag(), Some(&tag));
2964 assert_eq!(scalar.scalar(), Some(("value", ScalarStyle::DoubleQuoted)));
2965 assert!(scalar.is_node());
2966
2967 assert_eq!(sequence.anchor_id(), Some(8));
2968 assert_eq!(sequence.alias_id(), None);
2969 assert_eq!(sequence.tag(), Some(&tag));
2970 assert_eq!(sequence.scalar(), None);
2971 assert!(sequence.is_node());
2972
2973 assert_eq!(mapping.anchor_id(), Some(9));
2974 assert_eq!(mapping.alias_id(), None);
2975 assert_eq!(mapping.tag(), Some(&tag));
2976 assert_eq!(mapping.scalar(), None);
2977 assert!(mapping.is_node());
2978
2979 let alias = Event::Alias(10);
2980 assert_eq!(alias.anchor_id(), None);
2981 assert_eq!(alias.alias_id(), Some(10));
2982 assert_eq!(alias.tag(), None);
2983 assert_eq!(alias.scalar(), None);
2984 assert!(alias.is_node());
2985
2986 let unanchored_scalar = Event::Scalar("x".into(), ScalarStyle::Plain, 0, None);
2987 assert_eq!(unanchored_scalar.anchor_id(), None);
2988 assert_eq!(unanchored_scalar.alias_id(), None);
2989
2990 let stream_start = Event::StreamStart;
2991 assert_eq!(stream_start.anchor_id(), None);
2992 assert_eq!(stream_start.alias_id(), None);
2993 assert_eq!(stream_start.tag(), None);
2994 assert_eq!(stream_start.scalar(), None);
2995 assert!(!stream_start.is_node());
2996 }
2997
2998 #[test]
2999 fn test_peek_eq_parse() {
3000 let s = "
3001a0 bb: val
3002a1: &x
3003 b1: 4
3004 b2: d
3005a2: 4
3006a3: [1, 2, 3]
3007a4:
3008 - [a1, a2]
3009 - 2
3010a5: *x
3011";
3012 let mut p = Parser::new_from_str(s);
3013 loop {
3014 let event_peek = p.peek().unwrap().unwrap().clone();
3015 let event = p.next_event().unwrap().unwrap();
3016 assert_eq!(event, event_peek);
3017 if event.0 == Event::StreamEnd {
3018 break;
3019 }
3020 }
3021 }
3022
3023 #[test]
3024 fn test_repeated_peek_returns_buffered_event() {
3025 let mut parser = Parser::new_from_str("key: value\n");
3026
3027 let first_peek = parser.peek().unwrap().unwrap().clone();
3028 let second_peek = parser.peek().unwrap().unwrap().clone();
3029 let next = parser.next_event().unwrap().unwrap();
3030
3031 assert_eq!(first_peek, second_peek);
3032 assert_eq!(first_peek, next);
3033 }
3034
3035 #[cfg(feature = "error_messages")]
3036 #[test]
3037 fn test_peek_surfaces_scan_error_without_consuming_stream_end_state() {
3038 let mut parser = Parser::new_from_str("a: [1, 2");
3039
3040 loop {
3041 match parser.peek() {
3042 Some(Ok(_)) => {
3043 parser.next_event().unwrap().unwrap();
3044 }
3045 Some(Err(error)) => {
3046 assert_eq!(error.info(), "unclosed bracket '['");
3047 break;
3048 }
3049 None => panic!("expected parse error"),
3050 }
3051 }
3052 }
3053
3054 #[test]
3055 fn test_iterator_terminates_after_scan_error() {
3056 let parser = Parser::new_from_str("foo:\n bar\ninvalid\n");
3057 let mut errors = 0usize;
3058 let mut events = 0usize;
3059
3060 for item in parser {
3061 events += 1;
3062 if item.is_err() {
3063 errors += 1;
3064 }
3065 assert!(
3066 events < 1000,
3067 "parser iterator did not terminate after a scan error"
3068 );
3069 }
3070
3071 assert_eq!(errors, 1);
3072 }
3073
3074 #[cfg(feature = "error_messages")]
3075 #[test]
3076 fn test_iterator_terminates_after_node_property_error() {
3077 let parser = Parser::new_from_str("- *nope\n- 2\n");
3078 let mut errors = 0usize;
3079 let mut saw_later_node = false;
3080 let mut events = 0usize;
3081
3082 for item in parser {
3083 events += 1;
3084 match item {
3085 Ok((Event::Scalar(value, ..), _)) if value == "2" => saw_later_node = true,
3086 Ok(_) => {}
3087 Err(error) => {
3088 assert_eq!(error.info(), "while parsing node, found unknown anchor");
3089 errors += 1;
3090 }
3091 }
3092 assert!(
3093 events < 1000,
3094 "parser iterator did not terminate after a node-property error"
3095 );
3096 }
3097
3098 assert_eq!(errors, 1);
3099 assert!(!saw_later_node, "parser resumed after the alias error");
3100 }
3101
3102 #[test]
3103 fn test_peeked_scan_error_is_returned_once_by_next_event() {
3104 let mut parser = Parser::new_from_str("a: [1, 2");
3105
3106 let first_error = loop {
3107 match parser.peek() {
3108 Some(Ok(_)) => {
3109 parser.next_event().unwrap().unwrap();
3110 }
3111 Some(Err(error)) => break error,
3112 None => panic!("expected parse error"),
3113 }
3114 };
3115 let Some(Err(second_error)) = parser.peek() else {
3116 panic!("expected cached parse error");
3117 };
3118
3119 assert_eq!(first_error, second_error);
3120 assert_eq!(parser.next_event().unwrap().unwrap_err(), first_error);
3121 assert!(parser.next_event().is_none());
3122 assert!(parser.peek().is_none());
3123 }
3124
3125 #[cfg(feature = "error_messages")]
3126 #[test]
3127 fn test_peeked_node_property_error_is_stable_and_terminal() {
3128 let mut parser = Parser::new_from_str("a: *nope\nb: 2\n");
3129
3130 for _ in 0..4 {
3131 parser.next_event().unwrap().unwrap();
3132 }
3133
3134 let Some(Err(first_error)) = parser.peek() else {
3135 panic!("expected unknown alias error");
3136 };
3137 let Some(Err(second_error)) = parser.peek() else {
3138 panic!("expected cached unknown alias error");
3139 };
3140
3141 assert_eq!(first_error, second_error);
3142 assert_eq!(
3143 first_error.info(),
3144 "while parsing node, found unknown anchor"
3145 );
3146 assert_eq!(parser.next_event().unwrap().unwrap_err(), first_error);
3147 assert!(parser.next_event().is_none());
3148 assert!(parser.peek().is_none());
3149 }
3150
3151 #[test]
3152 fn test_peek_and_next_return_none_after_stream_end() {
3153 let mut parser = Parser::new_from_str("");
3154
3155 assert!(matches!(
3156 parser.next_event().unwrap().unwrap().0,
3157 Event::StreamStart
3158 ));
3159 assert!(matches!(
3160 parser.next_event().unwrap().unwrap().0,
3161 Event::StreamEnd
3162 ));
3163 assert!(parser.next_event().is_none());
3164 assert!(parser.peek().is_none());
3165 }
3166
3167 #[test]
3168 fn test_load_after_stream_already_ended_emits_stream_end() {
3169 let mut parser = Parser::new_from_str("");
3170 while parser.next_event().is_some() {}
3171
3172 let mut sink = CollectingSink::default();
3173 parser.load(&mut sink, true).unwrap();
3174
3175 assert_eq!(sink.events, vec![Event::StreamEnd]);
3176 }
3177
3178 #[test]
3179 fn test_load_full_stream_fuses_iterator_after_stream_end() {
3180 let mut parser = Parser::new_from_str("a: 1\n");
3181 let mut sink = CollectingSink::default();
3182
3183 parser.load(&mut sink, true).unwrap();
3184
3185 assert!(matches!(sink.events.last(), Some(Event::StreamEnd)));
3186 assert!(parser.next_event().is_none());
3187 assert!(parser.peek().is_none());
3188 }
3189
3190 #[test]
3191 fn test_load_after_peek_delivers_buffered_document_end_before_stream_end() {
3192 let mut parser = Parser::new_from_str("a");
3193 for _ in 0..3 {
3194 parser.next_event().unwrap().unwrap();
3195 }
3196
3197 assert_eq!(parser.peek().unwrap().unwrap().0, Event::DocumentEnd);
3198
3199 let mut sink = CollectingSink::default();
3200 parser.load(&mut sink, true).unwrap();
3201
3202 assert_eq!(sink.events, vec![Event::DocumentEnd, Event::StreamEnd]);
3203 assert!(parser.next_event().is_none());
3204 }
3205
3206 #[test]
3207 fn test_load_visits_nested_collection_events() {
3208 let mut parser = Parser::new_from_str("root:\n - item: value\n - [a, b]\n");
3209 let mut sink = CollectingSink::default();
3210
3211 parser.load(&mut sink, true).unwrap();
3212
3213 assert_eq!(
3214 sink.events,
3215 vec![
3216 Event::StreamStart,
3217 Event::DocumentStart(false, None),
3218 Event::MappingStart(StructureStyle::Block, 0, None),
3219 Event::Scalar("root".into(), ScalarStyle::Plain, 0, None),
3220 Event::SequenceStart(StructureStyle::Block, 0, None),
3221 Event::MappingStart(StructureStyle::Block, 0, None),
3222 Event::Scalar("item".into(), ScalarStyle::Plain, 0, None),
3223 Event::Scalar("value".into(), ScalarStyle::Plain, 0, None),
3224 Event::MappingEnd,
3225 Event::SequenceStart(StructureStyle::Flow, 0, None),
3226 Event::Scalar("a".into(), ScalarStyle::Plain, 0, None),
3227 Event::Scalar("b".into(), ScalarStyle::Plain, 0, None),
3228 Event::SequenceEnd,
3229 Event::SequenceEnd,
3230 Event::MappingEnd,
3231 Event::DocumentEnd,
3232 Event::StreamEnd,
3233 ]
3234 );
3235 }
3236
3237 #[derive(Clone, Debug, PartialEq, Eq)]
3238 enum ValidationError {
3239 ForbiddenValue,
3240 }
3241
3242 #[cfg(feature = "error_messages")]
3243 #[derive(Debug)]
3244 struct ReceiverFailure;
3245
3246 #[cfg(feature = "error_messages")]
3247 impl fmt::Display for ReceiverFailure {
3248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3249 write!(f, "receiver failed")
3250 }
3251 }
3252
3253 #[cfg(feature = "error_messages")]
3254 impl core::error::Error for ReceiverFailure {}
3255
3256 struct FailingSink<'input> {
3257 events: Vec<Event<'input>>,
3258 }
3259
3260 impl<'input> TryEventReceiver<'input> for FailingSink<'input> {
3261 type Error = ValidationError;
3262
3263 fn on_event(&mut self, ev: Event<'input>) -> Result<(), Self::Error> {
3264 let should_fail = matches!(&ev, Event::Scalar(value, ..) if value.as_ref() == "bad");
3265 self.events.push(ev);
3266 if should_fail {
3267 Err(ValidationError::ForbiddenValue)
3268 } else {
3269 Ok(())
3270 }
3271 }
3272 }
3273
3274 #[test]
3275 fn test_try_load_stops_on_receiver_error() {
3276 let mut parser = Parser::new_from_str("ok: bad\nafter: value\n");
3277 let mut sink = FailingSink { events: Vec::new() };
3278
3279 let err = parser.try_load(&mut sink, true).unwrap_err();
3280
3281 assert_eq!(err, TryLoadError::Receiver(ValidationError::ForbiddenValue));
3282 assert!(sink
3283 .events
3284 .iter()
3285 .any(|event| matches!(event, Event::Scalar(value, ..) if value == "ok")));
3286 assert!(sink
3287 .events
3288 .iter()
3289 .any(|event| matches!(event, Event::Scalar(value, ..) if value == "bad")));
3290 assert!(!sink
3291 .events
3292 .iter()
3293 .any(|event| matches!(event, Event::Scalar(value, ..) if value == "after")));
3294 }
3295
3296 struct SpannedFailingSink {
3297 failed_span: Option<Span>,
3298 }
3299
3300 impl<'input> TrySpannedEventReceiver<'input> for SpannedFailingSink {
3301 type Error = Span;
3302
3303 fn on_event(&mut self, ev: Event<'input>, span: Span) -> Result<(), Self::Error> {
3304 if matches!(ev, Event::Scalar(value, ..) if value.as_ref() == "bad") {
3305 self.failed_span = Some(span);
3306 Err(span)
3307 } else {
3308 Ok(())
3309 }
3310 }
3311 }
3312
3313 #[test]
3314 fn test_try_load_spanned_receiver_gets_span() {
3315 let mut parser = Parser::new_from_str("value: bad\n");
3316 let mut sink = SpannedFailingSink { failed_span: None };
3317
3318 let err = parser.try_load(&mut sink, false).unwrap_err();
3319
3320 let TryLoadError::Receiver(span) = err else {
3321 panic!("expected receiver error");
3322 };
3323
3324 assert_eq!(Some(span), sink.failed_span);
3325 assert!(!span.is_empty());
3326 }
3327
3328 #[cfg(feature = "error_messages")]
3329 struct NeverFails {
3330 count: usize,
3331 }
3332
3333 #[cfg(feature = "error_messages")]
3334 impl<'input> TryEventReceiver<'input> for NeverFails {
3335 type Error = ValidationError;
3336
3337 fn on_event(&mut self, _ev: Event<'input>) -> Result<(), Self::Error> {
3338 self.count += 1;
3339 Ok(())
3340 }
3341 }
3342
3343 #[cfg(feature = "error_messages")]
3344 #[test]
3345 fn test_try_load_returns_scan_error() {
3346 let mut parser = Parser::new_from_str("%YAML 1.2\n%YAML 1.2\n---\n");
3347 let mut sink = NeverFails { count: 0 };
3348
3349 let err = parser.try_load(&mut sink, true).unwrap_err();
3350
3351 let TryLoadError::Scan(err) = err else {
3352 panic!("expected scan error");
3353 };
3354 assert_eq!(err.kind(), &ErrorKind::DuplicateVersionDirective);
3355 assert_eq!(err.info(), "duplicate version directive");
3356 }
3357
3358 #[cfg(feature = "error_messages")]
3359 #[test]
3360 fn test_try_load_error_display_and_source_cover_both_variants() {
3361 let scan = ScanError::from_kind(Marker::new(3, 1, 3), ErrorKind::UnexpectedEof);
3362 let scan_err: TryLoadError<ReceiverFailure> = scan.into();
3363
3364 assert!(scan_err
3365 .to_string()
3366 .starts_with("parser error: unexpected eof"));
3367 assert!(scan_err.source().is_some());
3368
3369 let receiver_err = TryLoadError::Receiver(ReceiverFailure);
3370
3371 assert_eq!(receiver_err.to_string(), "receiver error: receiver failed");
3372 assert!(receiver_err.source().is_some());
3373 }
3374
3375 #[cfg(feature = "error_messages")]
3376 #[test]
3377 fn test_try_load_requires_buffered_stream_start() {
3378 let mut parser = Parser::new_from_str("");
3379 let span = Span::empty(Marker::new(0, 1, 0));
3380 parser.current = Some((
3381 Event::Scalar("value".into(), ScalarStyle::Plain, 0, None),
3382 span,
3383 ));
3384 let mut sink = NeverFails { count: 0 };
3385
3386 let err = parser.try_load(&mut sink, true).unwrap_err();
3387
3388 let TryLoadError::Scan(err) = err else {
3389 panic!("expected scan error");
3390 };
3391 assert_eq!(err.info(), "did not find expected <stream-start>");
3392 }
3393
3394 #[test]
3395 fn test_try_load_after_stream_already_ended_emits_stream_end() {
3396 let mut parser = Parser::new_from_str("");
3397 while parser.next_event().is_some() {}
3398
3399 let mut sink = FailingSink { events: Vec::new() };
3400 parser.try_load(&mut sink, true).unwrap();
3401
3402 assert_eq!(sink.events, vec![Event::StreamEnd]);
3403 }
3404
3405 #[test]
3406 fn test_try_load_full_stream_fuses_iterator_after_stream_end() {
3407 let mut parser = Parser::new_from_str("a: 1\n");
3408 let mut sink = FailingSink { events: Vec::new() };
3409
3410 parser.try_load(&mut sink, true).unwrap();
3411
3412 assert!(matches!(sink.events.last(), Some(Event::StreamEnd)));
3413 assert!(parser.next_event().is_none());
3414 assert!(parser.peek().is_none());
3415 }
3416
3417 #[test]
3418 fn test_try_load_after_peek_delivers_buffered_document_end_before_stream_end() {
3419 let mut parser = Parser::new_from_str("a");
3420 for _ in 0..3 {
3421 parser.next_event().unwrap().unwrap();
3422 }
3423
3424 assert_eq!(parser.peek().unwrap().unwrap().0, Event::DocumentEnd);
3425
3426 let mut sink = FailingSink { events: Vec::new() };
3427 parser.try_load(&mut sink, true).unwrap();
3428
3429 assert_eq!(sink.events, vec![Event::DocumentEnd, Event::StreamEnd]);
3430 assert!(parser.next_event().is_none());
3431 }
3432
3433 #[test]
3434 fn test_load_single_document_stops_before_next_document() {
3435 let mut parser = Parser::new_from_str("a: 1\n---\nb: 2\n");
3436 let mut sink = CollectingSink::default();
3437
3438 parser.load(&mut sink, false).unwrap();
3439
3440 assert!(sink
3441 .events
3442 .iter()
3443 .any(|event| matches!(event, Event::Scalar(value, ..) if value == "a")));
3444 assert!(!sink
3445 .events
3446 .iter()
3447 .any(|event| matches!(event, Event::Scalar(value, ..) if value == "b")));
3448 assert!(matches!(sink.events.last(), Some(Event::DocumentEnd)));
3449 }
3450
3451 #[cfg(feature = "error_messages")]
3452 #[test]
3453 fn test_duplicate_version_directive_errors() {
3454 assert_eq!(
3455 first_error_info("%YAML 1.2\n%YAML 1.2\n---\n"),
3456 "duplicate version directive"
3457 );
3458 }
3459
3460 #[cfg(feature = "error_messages")]
3461 #[test]
3462 fn test_unsupported_yaml_major_version_errors() {
3463 assert_eq!(
3464 first_error_info("%YAML 9.9\n--- a\n"),
3465 "unsupported YAML major version"
3466 );
3467 }
3468
3469 #[test]
3470 fn test_document_start_emits_yaml_version() {
3471 let events = Parser::new_from_str("%YAML 1.2\n---\nvalue\n")
3472 .map(|event| event.unwrap().0)
3473 .collect::<Vec<_>>();
3474
3475 assert!(matches!(
3476 events.get(1),
3477 Some(Event::DocumentStart(
3478 true,
3479 Some(YamlVersion { major: 1, minor: 2 })
3480 ))
3481 ));
3482 }
3483
3484 #[test]
3485 fn test_document_start_allows_supported_major_future_minor_version() {
3486 let events = Parser::new_from_str("%YAML 1.9\n---\nvalue\n")
3487 .map(|event| event.unwrap().0)
3488 .collect::<Vec<_>>();
3489
3490 assert!(matches!(
3491 events.get(1),
3492 Some(Event::DocumentStart(
3493 true,
3494 Some(YamlVersion { major: 1, minor: 9 })
3495 ))
3496 ));
3497 }
3498
3499 #[test]
3500 fn test_document_start_keeps_version_and_tags_across_comment() {
3501 let events = Parser::new_from_str(
3502 "%YAML 1.2\n# directive comment\n%TAG !e! tag:example.com,2026:\n---\nkey: !e!thing value\n",
3503 )
3504 .map(|event| event.unwrap().0)
3505 .collect::<Vec<_>>();
3506
3507 assert!(matches!(
3508 events.get(2),
3509 Some(Event::DocumentStart(
3510 true,
3511 Some(YamlVersion { major: 1, minor: 2 })
3512 ))
3513 ));
3514
3515 let tag = events
3516 .iter()
3517 .find_map(|event| match event {
3518 Event::Scalar(value, _, _, Some(tag)) if value == "value" => Some(tag),
3519 _ => None,
3520 })
3521 .expect("expected tagged scalar after comment-separated directives");
3522
3523 assert_eq!(tag.handle, "tag:example.com,2026:");
3524 assert_eq!(tag.suffix, "thing");
3525 }
3526
3527 #[test]
3528 fn tag_directive_state_borrows_str_input_across_comment() {
3529 let mut parser = Parser::new_from_str(
3530 "%TAG !e! tag:example.com,2026:\n# directive comment\n---\nkey: value\n",
3531 );
3532
3533 while let Some(event) = parser.next_event() {
3534 if matches!(event.unwrap().0, Event::Comment(..)) {
3535 break;
3536 }
3537 }
3538
3539 assert!(matches!(
3540 parser.tags.get("!e!"),
3541 Some(Cow::Borrowed("tag:example.com,2026:"))
3542 ));
3543 assert!(parser
3544 .pending_document_tag_handles
3545 .iter()
3546 .any(|handle| matches!(handle, Cow::Borrowed("!e!"))));
3547 }
3548
3549 #[test]
3550 fn test_each_document_can_declare_own_yaml_version() {
3551 let document_starts = Parser::new_from_str(
3552 "%YAML 1.2\n---\na\n...\n%YAML 1.2\n---\nb\n...\n%YAML 1.1\n---\nc\n",
3553 )
3554 .filter_map(|event| match event.unwrap().0 {
3555 Event::DocumentStart(explicit, version) => Some((explicit, version)),
3556 _ => None,
3557 })
3558 .collect::<Vec<_>>();
3559
3560 assert_eq!(
3561 document_starts,
3562 vec![
3563 (true, Some(YamlVersion::new(1, 2))),
3564 (true, Some(YamlVersion::new(1, 2))),
3565 (true, Some(YamlVersion::new(1, 1))),
3566 ]
3567 );
3568 }
3569
3570 #[cfg(feature = "error_messages")]
3571 #[test]
3572 fn test_duplicate_tag_directive_errors() {
3573 assert_eq!(
3574 first_error_info("%TAG !t! tag:test,2024:\n%TAG !t! tag:other,2024:\n---\n"),
3575 "the TAG directive must only be given at most once per handle in the same document"
3576 );
3577 }
3578
3579 #[cfg(feature = "error_messages")]
3580 #[test]
3581 fn duplicate_tag_directive_across_comment_is_rejected() {
3582 let input = concat!(
3583 "%TAG !e! tag:example.com,2000:one/\n",
3584 "# separator\n",
3585 "%TAG !e! tag:example.com,2000:two/\n",
3586 "---\n",
3587 );
3588
3589 assert_eq!(
3590 first_error_info(input),
3591 "the TAG directive must only be given at most once per handle in the same document"
3592 );
3593 }
3594
3595 #[test]
3596 fn test_keep_tags_inherited_handle_can_be_redeclared_in_next_document() {
3597 let input = concat!(
3598 "%TAG !e! tag:example.com,2000:one/\n",
3599 "---\n",
3600 "first: !e!thing value\n",
3601 "...\n",
3602 "%TAG !e! tag:example.com,2000:two/\n",
3603 "---\n",
3604 "second: !e!thing value\n",
3605 );
3606
3607 let tags = Parser::new_from_str(input)
3608 .keep_tags(true)
3609 .filter_map(|event| match event.expect("input should parse").0 {
3610 Event::Scalar(value, _, _, Some(tag)) if value == "value" => {
3611 Some(tag.handle.clone())
3612 }
3613 _ => None,
3614 })
3615 .collect::<Vec<_>>();
3616
3617 assert_eq!(
3618 tags,
3619 vec!["tag:example.com,2000:one/", "tag:example.com,2000:two/"]
3620 );
3621 }
3622
3623 #[cfg(feature = "error_messages")]
3624 #[test]
3625 fn test_directive_after_implicit_document_requires_explicit_end() {
3626 assert_eq!(
3627 first_error_info("---\nkey: value\n%YAML 1.2\n---\n"),
3628 "missing explicit document end marker before directive"
3629 );
3630 }
3631
3632 #[cfg(feature = "error_messages")]
3633 #[test]
3634 fn test_anchor_offset_overflow_reports_error() {
3635 let mut parser = Parser::new_from_str("&a value");
3636 parser.set_anchor_offset(usize::MAX);
3637
3638 let err = parser
3639 .find_map(Result::err)
3640 .expect("anchor registration should overflow");
3641
3642 assert_eq!(
3643 err.info(),
3644 "while parsing anchor, anchor count exceeded supported limit"
3645 );
3646 }
3647
3648 #[test]
3649 fn test_alias_resolves_to_registered_anchor_id() {
3650 let events = Parser::new_from_str("- &a value\n- *a\n")
3651 .map(|event| event.unwrap().0)
3652 .collect::<Vec<_>>();
3653
3654 assert!(events.iter().any(|event| matches!(event, Event::Alias(1))));
3655 }
3656
3657 #[test]
3658 fn test_anchor_then_tag_applies_both_to_scalar() {
3659 let events = Parser::new_from_str("&a !!str value")
3660 .map(|event| event.unwrap().0)
3661 .collect::<Vec<_>>();
3662
3663 let Some(Event::Scalar(value, _, anchor_id, Some(tag))) = events
3664 .iter()
3665 .find(|event| matches!(event, Event::Scalar(value, ..) if value == "value"))
3666 else {
3667 panic!("expected tagged anchored scalar");
3668 };
3669
3670 assert_eq!(value, "value");
3671 assert_eq!(*anchor_id, 1);
3672 assert_eq!(tag.handle, "tag:yaml.org,2002:");
3673 assert_eq!(tag.suffix, "str");
3674 assert_eq!(tag.original_handle, "!!");
3675 assert_eq!(tag.original(), "!!str");
3676 }
3677
3678 #[test]
3679 fn test_tag_then_anchor_applies_both_to_scalar() {
3680 let events = Parser::new_from_str("!!str &a value")
3681 .map(|event| event.unwrap().0)
3682 .collect::<Vec<_>>();
3683
3684 let Some(Event::Scalar(value, _, anchor_id, Some(tag))) = events
3685 .iter()
3686 .find(|event| matches!(event, Event::Scalar(value, ..) if value == "value"))
3687 else {
3688 panic!("expected tagged anchored scalar");
3689 };
3690
3691 assert_eq!(value, "value");
3692 assert_eq!(*anchor_id, 1);
3693 assert_eq!(tag.handle, "tag:yaml.org,2002:");
3694 assert_eq!(tag.suffix, "str");
3695 assert_eq!(tag.original_handle, "!!");
3696 assert_eq!(tag.original(), "!!str");
3697 }
3698
3699 #[test]
3700 fn test_tag_directive_preserves_original_handle() {
3701 let events =
3702 Parser::new_from_str("%TAG !e! tag:example.com,2000:\n---\nconfig: !e!keep value\n")
3703 .map(|event| event.unwrap().0)
3704 .collect::<Vec<_>>();
3705
3706 let (value, tag) = events
3707 .iter()
3708 .find_map(|event| match event {
3709 Event::Scalar(value, _, _, Some(tag)) if value == "value" => Some((value, tag)),
3710 _ => None,
3711 })
3712 .expect("expected tagged scalar");
3713
3714 assert_eq!(value, "value");
3715 assert_eq!(tag.handle, "tag:example.com,2000:");
3716 assert_eq!(tag.suffix, "keep");
3717 assert_eq!(tag.original_handle, "!e!");
3718 assert_eq!(tag.parts(), ("tag:example.com,2000:", "keep"));
3719 assert_eq!(tag.original_parts(), ("!e!", "keep"));
3720 assert_eq!(tag.original(), "!e!keep");
3721 }
3722
3723 #[test]
3724 fn test_verbatim_tag_original_is_normalized_author_spelling() {
3725 let events = Parser::new_from_str("key: !<tag:example.com,2000:thing> value\n")
3726 .map(|event| event.unwrap().0)
3727 .collect::<Vec<_>>();
3728
3729 let Some(Event::Scalar(value, _, _, Some(tag))) = events
3730 .iter()
3731 .find(|event| matches!(event, Event::Scalar(value, ..) if value == "value"))
3732 else {
3733 panic!("expected tagged scalar");
3734 };
3735
3736 assert_eq!(value, "value");
3737 assert_eq!(tag.handle, "");
3738 assert_eq!(tag.suffix, "tag:example.com,2000:thing");
3739 assert_eq!(tag.original_handle, "");
3740 assert_eq!(tag.parts(), ("", "tag:example.com,2000:thing"));
3741 assert_eq!(tag.original_parts(), ("", "tag:example.com,2000:thing"));
3742 assert_eq!(tag.original(), "!<tag:example.com,2000:thing>");
3743 }
3744
3745 #[test]
3746 fn test_multiple_tag_directives_are_kept_within_document() {
3747 let text = r"
3748%TAG !a! tag:a,2024:
3749%TAG !b! tag:b,2024:
3750---
3751first: !a!x foo
3752second: !b!y bar
3753";
3754
3755 let mut seen_a = false;
3756 let mut seen_b = false;
3757 for event in Parser::new_from_str(text) {
3758 let (event, _) = event.unwrap();
3759 if let Event::Scalar(_, _, _, Some(tag)) = event {
3760 if tag.handle == "tag:a,2024:" {
3761 seen_a = true;
3762 } else if tag.handle == "tag:b,2024:" {
3763 seen_b = true;
3764 }
3765 }
3766 }
3767
3768 assert!(seen_a);
3769 assert!(seen_b);
3770 }
3771
3772 #[cfg(feature = "error_messages")]
3773 #[test]
3774 fn test_tags_are_cleared_when_next_document_has_no_directives() {
3775 let text = r"
3776%TAG !t! tag:test,2024:
3777--- !t!1
3778foo
3779--- !t!2
3780bar
3781";
3782
3783 let mut parser = Parser::new_from_str(text);
3784 for event in parser.by_ref() {
3785 let (event, _) = event.unwrap();
3786 if let Event::DocumentEnd = event {
3787 break;
3788 }
3789 }
3790
3791 match parser.next().unwrap().unwrap().0 {
3792 Event::DocumentStart(true, None) => {}
3793 _ => panic!("expected explicit second document start"),
3794 }
3795
3796 let err = parser.next().unwrap().unwrap_err();
3797 assert!(format!("{err}").contains("the handle wasn't declared"));
3798 }
3799
3800 #[cfg(feature = "error_messages")]
3801 #[test]
3802 fn test_pull_parser_clears_anchors_between_documents() {
3803 let mut parser = Parser::new_from_str(
3804 "--- &a value
3805--- *a
3806",
3807 );
3808
3809 for event in parser.by_ref() {
3810 let (event, _) = event.unwrap();
3811 if matches!(event, Event::DocumentEnd) {
3812 break;
3813 }
3814 }
3815
3816 match parser.next().unwrap().unwrap().0 {
3817 Event::DocumentStart(true, None) => {}
3818 _ => panic!("expected explicit second document start"),
3819 }
3820
3821 let err = parser.next().unwrap().unwrap_err();
3822 assert!(format!("{err}").contains("unknown anchor"));
3823 }
3824
3825 #[test]
3826 fn test_keep_tags_across_multiple_documents() {
3827 let text = r#"
3828%YAML 1.1
3829%TAG !t! tag:test,2024:
3830--- !t!1 &1
3831foo: "bar"
3832--- !t!2 &2
3833baz: "qux"
3834"#;
3835 for x in Parser::new_from_str(text).keep_tags(true) {
3836 let x = x.unwrap();
3837 if let Event::MappingStart(_, _, tag) = x.0 {
3838 let tag = tag.unwrap();
3839 assert_eq!(tag.handle, "tag:test,2024:");
3840 }
3841 }
3842
3843 for x in Parser::new_from_str(text).keep_tags(false) {
3844 if x.is_err() {
3845 return;
3847 }
3848 }
3849 panic!("Test failed, did not encounter error")
3850 }
3851
3852 #[test]
3853 fn test_flow_sequence_mapping_allows_empty_key() {
3854 let parser = Parser::new_from_str("[?: value]");
3855 for event in parser {
3856 event.expect("parser should accept flow sequence mappings with empty keys");
3857 }
3858 }
3859
3860 #[test]
3861 fn test_keep_tags_does_not_persist_default_tag_handles() {
3862 let text = "%TAG !! tag:evil,2024:\n--- !!int 1\n--- !!int 2\n";
3863
3864 let mut int_tags = Vec::new();
3865 for event in Parser::new_from_str(text).keep_tags(true) {
3866 let event = event.unwrap().0;
3867 if let Event::Scalar(_, _, _, Some(tag)) = event {
3868 if tag.suffix == "int" {
3869 int_tags.push(tag.handle.clone());
3870 }
3871 }
3872 }
3873
3874 assert_eq!(int_tags, vec!["tag:evil,2024:", "tag:yaml.org,2002:"]);
3875 }
3876
3877 #[test]
3878 fn test_keep_tags_does_not_persist_primary_tag_handle() {
3879 let text = "%TAG ! tag:evil,2024:\n--- !int 1\n--- !int 2\n";
3880
3881 let tags = Parser::new_from_str(text)
3882 .keep_tags(true)
3883 .filter_map(|event| match event.expect("input should parse").0 {
3884 Event::Scalar(_, _, _, Some(tag)) if tag.suffix == "int" => {
3885 Some(tag.handle.clone())
3886 }
3887 _ => None,
3888 })
3889 .collect::<Vec<_>>();
3890
3891 assert_eq!(tags, vec!["tag:evil,2024:", "!"]);
3892 }
3893
3894 #[test]
3895 fn test_resolve_tag_uses_overridden_local_prefix() {
3896 let mut parser = Parser::new_from_str("");
3897 parser
3898 .tags
3899 .insert("!".into(), "tag:local.example,2024:".into());
3900
3901 let tag = parser
3902 .resolve_tag(
3903 Span::empty(Marker::new(0, 1, 0)),
3904 &Cow::Borrowed(""),
3905 Cow::Borrowed("!"),
3906 )
3907 .unwrap();
3908
3909 assert_eq!(tag.handle, "tag:local.example,2024:");
3910 assert_eq!(tag.suffix, "!");
3911 }
3912
3913 #[test]
3914 fn test_load_after_peek_stream_start() {
3915 #[derive(Default)]
3916 struct Sink<'input> {
3917 events: Vec<Event<'input>>,
3918 }
3919
3920 impl<'input> EventReceiver<'input> for Sink<'input> {
3921 fn on_event(&mut self, ev: Event<'input>) {
3922 self.events.push(ev);
3923 }
3924 }
3925
3926 let mut parser = Parser::new_from_str("key: value\n");
3927 let mut sink = Sink::default();
3928
3929 assert_eq!(parser.peek().unwrap().unwrap().0, Event::StreamStart);
3930 parser.load(&mut sink, false).unwrap();
3931
3932 assert!(matches!(sink.events.first(), Some(Event::StreamStart)));
3933 assert!(matches!(sink.events.get(1), Some(Event::DocumentStart(..))));
3934 }
3935}