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