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