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