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