1use crate::{
4 error::ErrorContext, tag::TagResolver, BasicScanner, Error, Limits, Position, Result, Scanner,
5 Token, TokenType,
6};
7
8pub mod events;
9pub mod streaming;
10pub use events::*;
12pub use streaming::*;
13pub trait Parser {
17 fn check_event(&self) -> bool;
19
20 fn peek_event(&self) -> Result<Option<&Event>>;
22
23 fn get_event(&mut self) -> Result<Option<Event>>;
25
26 fn reset(&mut self);
28
29 fn position(&self) -> Position;
31}
32
33#[derive(Debug)]
35pub struct BasicParser {
36 scanner: BasicScanner,
37 events: Vec<Event>,
38 event_index: usize,
39 state: ParserState,
40 state_stack: Vec<ParserState>,
41 position: Position,
42 pending_anchor: Option<String>,
43 pending_tag: Option<String>,
44 last_token_type: Option<TokenType>,
45 scanning_error: Option<Error>,
46 yaml_version: Option<(u8, u8)>,
47 tag_directives: Vec<(String, String)>,
48 tag_resolver: TagResolver,
49}
50
51#[derive(Debug, Clone, Copy, PartialEq)]
53#[allow(dead_code)]
54enum ParserState {
55 StreamStart,
56 StreamEnd,
57 ImplicitDocumentStart,
58 DocumentStart,
59 DocumentContent,
60 DocumentEnd,
61 BlockNode,
62 BlockMapping,
63 BlockMappingKey,
64 BlockMappingValue,
65 BlockSequence,
66 FlowMapping,
67 FlowMappingKey,
68 FlowMappingValue,
69 FlowSequence,
70 BlockEnd,
71}
72
73impl BasicParser {
74 pub fn new(input: String) -> Self {
76 Self::with_limits(input, Limits::default())
77 }
78
79 pub fn with_limits(input: String, limits: Limits) -> Self {
81 let scanner = BasicScanner::with_limits(input, limits);
82 let position = scanner.position();
83
84 Self {
85 scanner,
86 events: Vec::new(),
87 event_index: 0,
88 state: ParserState::StreamStart,
89 state_stack: Vec::new(),
90 position,
91 pending_anchor: None,
92 pending_tag: None,
93 last_token_type: None,
94 scanning_error: None,
95 yaml_version: None,
96 tag_directives: Vec::new(),
97 tag_resolver: TagResolver::new(),
98 }
99 }
100
101 pub fn new_eager(input: String) -> Self {
103 Self::new_eager_with_limits(input, Limits::default())
104 }
105
106 pub fn new_eager_with_limits(input: String, limits: Limits) -> Self {
108 let mut scanner = BasicScanner::new_eager_with_limits(input, limits);
109 let position = scanner.position();
110
111 let scanning_error = scanner.take_scanning_error();
113
114 let mut parser = Self {
115 scanner,
116 events: Vec::new(),
117 event_index: 0,
118 state: ParserState::StreamStart,
119 state_stack: Vec::new(),
120 position,
121 pending_anchor: None,
122 pending_tag: None,
123 last_token_type: None,
124 scanning_error: None,
125 yaml_version: None,
126 tag_directives: Vec::new(),
127 tag_resolver: TagResolver::new(),
128 };
129
130 if let Some(error) = scanning_error {
132 parser.scanning_error = Some(error);
133 } else {
134 parser.parse_all().unwrap_or(());
136 }
137
138 parser
139 }
140
141 pub fn from_scanner(scanner: BasicScanner) -> Self {
143 let position = scanner.position();
144
145 let mut parser = Self {
146 scanner,
147 events: Vec::new(),
148 event_index: 0,
149 state: ParserState::StreamStart,
150 state_stack: Vec::new(),
151 position,
152 pending_anchor: None,
153 pending_tag: None,
154 last_token_type: None,
155 scanning_error: None,
156 yaml_version: None,
157 tag_directives: Vec::new(),
158 tag_resolver: TagResolver::new(),
159 };
160
161 parser.parse_all().unwrap_or(());
162 parser
163 }
164
165 fn parse_all(&mut self) -> Result<()> {
167 while self.scanner.check_token() {
168 let token = match self.scanner.get_token()? {
169 Some(token) => token,
170 None => break,
171 };
172
173 self.position = token.end_position;
174 self.process_token(token)?;
175 }
176
177 self.validate_final_state()?;
179
180 if !self
182 .events
183 .iter()
184 .any(|e| matches!(e.event_type, EventType::StreamEnd))
185 {
186 self.events.push(Event::stream_end(self.position));
187 }
188
189 Ok(())
190 }
191
192 fn create_implicit_document_start(&mut self, position: Position) -> Event {
194 let event = Event::document_start(
195 position,
196 self.yaml_version.take(),
197 self.tag_directives.clone(),
198 true,
199 );
200 self.tag_directives.clear();
201 event
202 }
203
204 fn validate_final_state(&self) -> Result<()> {
206 match self.state {
207 ParserState::StreamEnd | ParserState::DocumentEnd | ParserState::DocumentContent => {
208 Ok(())
210 }
211 ParserState::BlockSequence | ParserState::FlowSequence => {
212 let context = ErrorContext::from_input(self.scanner.input(), &self.position, 2)
213 .with_suggestion(
214 "Close the sequence with proper indentation or closing bracket".to_string(),
215 );
216 Err(Error::unclosed_delimiter_with_context(
217 self.position,
218 self.position,
219 "sequence",
220 context,
221 ))
222 }
223 ParserState::BlockMapping | ParserState::FlowMapping => {
224 let context = ErrorContext::from_input(self.scanner.input(), &self.position, 2)
225 .with_suggestion(
226 "Close the mapping with proper indentation or closing brace".to_string(),
227 );
228 Err(Error::unclosed_delimiter_with_context(
229 self.position,
230 self.position,
231 "mapping",
232 context,
233 ))
234 }
235 _ => {
236 let context = ErrorContext::from_input(self.scanner.input(), &self.position, 2)
237 .with_suggestion("Complete the YAML document structure".to_string());
238 Err(Error::parse_with_context(
239 self.position,
240 format!("Document ended in unexpected state: {:?}", self.state),
241 context,
242 ))
243 }
244 }
245 }
246
247 fn generate_next_event(&mut self) -> Result<()> {
249 if let Some(token) = self.scanner.get_token()? {
250 self.position = token.end_position;
251 self.process_token(token)?;
252 }
253 Ok(())
254 }
255
256 #[allow(clippy::cognitive_complexity)]
258 fn process_token(&mut self, token: Token) -> Result<()> {
259 let token_type_for_tracking = match &token.token_type {
261 TokenType::Scalar(..) => Some(TokenType::Scalar(
262 String::new(),
263 crate::scanner::QuoteStyle::Plain,
264 )),
265 TokenType::BlockScalarLiteral(..) => Some(TokenType::BlockScalarLiteral(String::new())),
266 TokenType::BlockScalarFolded(..) => Some(TokenType::BlockScalarFolded(String::new())),
267 TokenType::Alias(..) => Some(TokenType::Alias(String::new())),
268 TokenType::Anchor(..) => Some(TokenType::Anchor(String::new())),
269 TokenType::Tag(..) => Some(TokenType::Tag(String::new())),
270 TokenType::Comment(..) => Some(TokenType::Comment(String::new())),
271 other => {
272 match other {
274 TokenType::StreamStart => Some(TokenType::StreamStart),
275 TokenType::StreamEnd => Some(TokenType::StreamEnd),
276 TokenType::DocumentStart => Some(TokenType::DocumentStart),
277 TokenType::DocumentEnd => Some(TokenType::DocumentEnd),
278 TokenType::BlockSequenceStart => Some(TokenType::BlockSequenceStart),
279 TokenType::BlockMappingStart => Some(TokenType::BlockMappingStart),
280 TokenType::BlockEnd => Some(TokenType::BlockEnd),
281 TokenType::FlowSequenceStart => Some(TokenType::FlowSequenceStart),
282 TokenType::FlowSequenceEnd => Some(TokenType::FlowSequenceEnd),
283 TokenType::FlowMappingStart => Some(TokenType::FlowMappingStart),
284 TokenType::FlowMappingEnd => Some(TokenType::FlowMappingEnd),
285 TokenType::BlockEntry => Some(TokenType::BlockEntry),
286 TokenType::FlowEntry => Some(TokenType::FlowEntry),
287 TokenType::Key => Some(TokenType::Key),
288 TokenType::Value => Some(TokenType::Value),
289 TokenType::YamlDirective(_, _) => Some(TokenType::YamlDirective(0, 0)),
290 TokenType::TagDirective(_, _) => {
291 Some(TokenType::TagDirective(String::new(), String::new()))
292 }
293 _ => None,
294 }
295 }
296 };
297
298 match &token.token_type {
299 TokenType::StreamStart => {
300 self.events.push(Event::stream_start(token.start_position));
301 self.state = ParserState::ImplicitDocumentStart;
302 }
303
304 TokenType::StreamEnd => {
305 if matches!(
307 self.state,
308 ParserState::DocumentContent | ParserState::BlockNode
309 ) {
310 self.events
311 .push(Event::document_end(token.start_position, true));
312 }
313 self.events.push(Event::stream_end(token.start_position));
314 self.state = ParserState::StreamEnd;
315 }
316
317 TokenType::YamlDirective(major, minor) => {
318 self.yaml_version = Some((*major, *minor));
320 }
322
323 TokenType::TagDirective(handle, prefix) => {
324 self.tag_directives.push((handle.clone(), prefix.clone()));
326 self.tag_resolver
327 .add_directive(handle.clone(), prefix.clone());
328 }
330
331 TokenType::DocumentStart => {
332 if matches!(
334 self.state,
335 ParserState::DocumentContent | ParserState::BlockNode
336 ) {
337 self.events
338 .push(Event::document_end(token.start_position, true));
339 }
340
341 self.events.push(Event::document_start(
343 token.start_position,
344 self.yaml_version.take(),
345 self.tag_directives.clone(),
346 false,
347 ));
348
349 self.tag_directives.clear();
352
353 self.state = ParserState::DocumentStart;
354 }
355
356 TokenType::DocumentEnd => {
357 self.events
358 .push(Event::document_end(token.start_position, false));
359 self.state = ParserState::DocumentEnd;
360 }
361
362 TokenType::BlockSequenceStart => {
363 if matches!(self.state, ParserState::ImplicitDocumentStart) {
364 let event = self.create_implicit_document_start(token.start_position);
365 self.events.push(event);
366 }
367
368 if matches!(
370 self.state,
371 ParserState::BlockMappingValue | ParserState::BlockMappingKey
372 ) {
373 self.state_stack.push(self.state);
374 }
375
376 self.events.push(Event::sequence_start(
377 token.start_position,
378 self.pending_anchor.take(),
379 self.pending_tag.take(),
380 false,
381 ));
382 self.state = ParserState::BlockSequence;
383 }
384
385 TokenType::BlockMappingStart => {
386 let should_create_new_mapping = match self.state {
391 ParserState::ImplicitDocumentStart => {
392 true
394 }
395 ParserState::DocumentStart => {
396 true
398 }
399 ParserState::DocumentContent => {
400 let mut mapping_depth = 0;
407 let mut has_unclosed_mapping = false;
408
409 for event in self.events.iter().rev() {
410 match &event.event_type {
411 EventType::MappingEnd => mapping_depth += 1,
412 EventType::MappingStart { .. } => {
413 if mapping_depth == 0 {
414 has_unclosed_mapping = true;
415 break;
416 }
417 mapping_depth -= 1;
418 }
419 EventType::DocumentStart { .. } => break,
420 _ => {}
421 }
422 }
423
424 !has_unclosed_mapping
426 }
427 ParserState::BlockMappingValue => {
428 true
430 }
431 ParserState::BlockMappingKey => {
432 matches!(
437 &self.last_token_type,
438 Some(TokenType::Key | TokenType::Value)
439 )
440 }
441 ParserState::BlockSequence => {
442 true
445 }
446 _ => {
447 matches!(
449 &self.last_token_type,
450 Some(TokenType::Key | TokenType::Value)
451 )
452 }
453 };
454
455 if should_create_new_mapping {
456 if matches!(self.state, ParserState::ImplicitDocumentStart) {
458 let event = self.create_implicit_document_start(token.start_position);
459 self.events.push(event);
460 }
461
462 if matches!(
464 self.state,
465 ParserState::BlockMappingValue | ParserState::BlockSequence
466 ) {
467 self.state_stack.push(self.state);
468 }
469
470 self.events.push(Event::mapping_start(
471 token.start_position,
472 self.pending_anchor.take(),
473 self.pending_tag.take(),
474 false,
475 ));
476 self.state = ParserState::BlockMappingKey;
477 } else {
478 match self.state {
481 ParserState::DocumentContent => {
482 self.state = ParserState::BlockMappingKey;
484 }
485 ParserState::BlockMappingValue => {
486 self.state = ParserState::BlockMappingKey;
488 }
489 ParserState::BlockMappingKey => {
490 }
492 _ => {
493 if let Some(prev_state) = self.state_stack.last() {
495 if matches!(prev_state, ParserState::BlockMappingValue) {
496 if let Some(mapping_state) = self.state_stack.pop() {
497 self.state = mapping_state;
498 self.handle_node_completion();
499 }
500 }
501 }
502 }
503 }
504 }
505 }
506
507 TokenType::FlowSequenceStart => {
508 if matches!(self.state, ParserState::ImplicitDocumentStart) {
509 self.events.push(Event::document_start(
510 token.start_position,
511 None,
512 vec![],
513 true,
514 ));
515 }
516 self.events.push(Event::sequence_start(
517 token.start_position,
518 self.pending_anchor.take(),
519 self.pending_tag.take(),
520 true,
521 ));
522 self.state = ParserState::FlowSequence;
523 }
524
525 TokenType::FlowMappingStart => {
526 if matches!(self.state, ParserState::ImplicitDocumentStart) {
527 self.events.push(Event::document_start(
528 token.start_position,
529 None,
530 vec![],
531 true,
532 ));
533 }
534 self.events.push(Event::mapping_start(
535 token.start_position,
536 self.pending_anchor.take(),
537 self.pending_tag.take(),
538 true,
539 ));
540 self.state = ParserState::FlowMapping;
541 }
542
543 TokenType::FlowSequenceEnd => {
544 self.events.push(Event::sequence_end(token.start_position));
545 self.state = ParserState::DocumentContent;
546
547 self.handle_node_completion();
549 }
550
551 TokenType::FlowMappingEnd => {
552 self.events.push(Event::mapping_end(token.start_position));
553 self.state = ParserState::DocumentContent;
554
555 self.handle_node_completion();
557 }
558
559 TokenType::BlockEnd => {
560 match self.state {
562 ParserState::BlockSequence => {
563 self.events.push(Event::sequence_end(token.start_position));
564 if let Some(prev_state) = self.state_stack.pop() {
566 self.state = prev_state;
567 self.handle_node_completion();
569 } else {
570 self.state = ParserState::DocumentContent;
571 }
572 }
573 ParserState::BlockMapping
574 | ParserState::BlockMappingKey
575 | ParserState::BlockMappingValue => {
576 self.events.push(Event::mapping_end(token.start_position));
577 if let Some(prev_state) = self.state_stack.pop() {
579 self.state = prev_state;
580 if matches!(self.state, ParserState::BlockMappingValue) {
582 self.handle_node_completion();
583 }
584 } else {
585 let mut mapping_depth = 0;
588
589 for event in self.events.iter().rev() {
590 match &event.event_type {
591 EventType::MappingEnd => {
592 mapping_depth += 1;
593 }
594 EventType::MappingStart { .. } => {
595 if mapping_depth > 0 {
596 mapping_depth -= 1;
597 } else {
598 self.state = ParserState::BlockMappingKey;
600 return Ok(());
601 }
602 }
603 EventType::DocumentStart { .. } => break,
604 _ => {}
605 }
606 }
607
608 self.state = ParserState::DocumentContent;
610 }
611 }
612 _ => {}
613 }
614 }
615
616 TokenType::Scalar(value, quote_style) => {
617 if matches!(self.state, ParserState::ImplicitDocumentStart) {
618 self.events.push(Event::document_start(
619 token.start_position,
620 None,
621 vec![],
622 true,
623 ));
624 self.state = ParserState::DocumentContent;
625 }
626
627 if matches!(self.state, ParserState::BlockSequence) {
629 if let Ok(Some(next_token)) = self.scanner.peek_token() {
630 if matches!(next_token.token_type, TokenType::Value) {
631 self.state_stack.push(self.state);
634 self.events.push(Event::mapping_start(
635 token.start_position,
636 self.pending_anchor.take(),
637 self.pending_tag.take(),
638 false,
639 ));
640 self.state = ParserState::BlockMappingKey;
641 }
642 }
643 }
644
645 let style = match quote_style {
647 crate::scanner::QuoteStyle::Plain => ScalarStyle::Plain,
648 crate::scanner::QuoteStyle::Single => ScalarStyle::SingleQuoted,
649 crate::scanner::QuoteStyle::Double => ScalarStyle::DoubleQuoted,
650 };
651
652 self.events.push(Event::scalar(
653 token.start_position,
654 self.pending_anchor.take(), self.pending_tag.take(), value.clone(),
657 style == ScalarStyle::Plain,
658 style != ScalarStyle::Plain,
659 style,
660 ));
661
662 self.handle_node_completion();
664 }
665
666 TokenType::BlockScalarLiteral(value) => {
667 if matches!(self.state, ParserState::ImplicitDocumentStart) {
668 self.events.push(Event::document_start(
669 token.start_position,
670 None,
671 vec![],
672 true,
673 ));
674 self.state = ParserState::DocumentContent;
675 }
676
677 self.events.push(Event::scalar(
678 token.start_position,
679 self.pending_anchor.take(), self.pending_tag.take(), value.clone(),
682 false, true, ScalarStyle::Literal,
685 ));
686
687 self.handle_node_completion();
689 }
690
691 TokenType::BlockScalarFolded(value) => {
692 if matches!(self.state, ParserState::ImplicitDocumentStart) {
693 self.events.push(Event::document_start(
694 token.start_position,
695 None,
696 vec![],
697 true,
698 ));
699 self.state = ParserState::DocumentContent;
700 }
701
702 self.events.push(Event::scalar(
703 token.start_position,
704 self.pending_anchor.take(), self.pending_tag.take(), value.clone(),
707 false, true, ScalarStyle::Folded,
710 ));
711
712 self.handle_node_completion();
714 }
715
716 TokenType::BlockEntry => {
717 match self.state {
720 ParserState::BlockSequence => {
721 }
724 ParserState::BlockMapping | ParserState::BlockMappingValue => {
725 self.events.push(Event::mapping_end(token.start_position));
728 self.state = ParserState::BlockSequence;
729 }
730 _ => {
731 if matches!(self.state, ParserState::ImplicitDocumentStart) {
734 self.events.push(Event::document_start(
735 token.start_position,
736 None,
737 vec![],
738 true,
739 ));
740 }
741
742 self.events.push(Event::sequence_start(
744 token.start_position,
745 self.pending_anchor.take(),
746 self.pending_tag.take(),
747 false,
748 ));
749 self.state = ParserState::BlockSequence;
750 }
751 }
752 }
753
754 TokenType::Value => {
755 match self.state {
757 ParserState::BlockMappingKey => {
758 self.state = ParserState::BlockMappingValue;
759 }
760 ParserState::FlowMappingKey => {
761 self.state = ParserState::FlowMappingValue;
762 }
763 _ => {
764 }
767 }
768 }
769
770 TokenType::FlowEntry => {
771 }
773
774 TokenType::Anchor(name) => {
775 self.pending_anchor = Some(name.clone());
777 }
778
779 TokenType::Alias(name) => {
780 if matches!(self.state, ParserState::ImplicitDocumentStart) {
781 self.events.push(Event::document_start(
782 token.start_position,
783 None,
784 vec![],
785 true,
786 ));
787 self.state = ParserState::DocumentContent;
788 }
789
790 self.events
792 .push(Event::alias(token.start_position, name.clone()));
793
794 self.handle_node_completion();
796 }
797
798 TokenType::Tag(tag) => {
799 match self.tag_resolver.resolve(&tag) {
801 Ok(resolved_tag) => {
802 self.pending_tag = Some(resolved_tag.uri);
803 }
804 Err(_) => {
805 self.pending_tag = Some(tag.clone());
807 }
808 }
809 }
810
811 TokenType::Comment(_) => {
813 }
815
816 TokenType::Key => {
818 match self.state {
819 ParserState::ImplicitDocumentStart => {
820 let event = self.create_implicit_document_start(token.start_position);
822 self.events.push(event);
823 self.events.push(Event::mapping_start(
824 token.start_position,
825 self.pending_anchor.take(),
826 self.pending_tag.take(),
827 false,
828 ));
829 self.state = ParserState::BlockMappingKey;
830 }
831 ParserState::DocumentContent => {
832 if !self.events.is_empty() {
835 if let Some(last_event) = self.events.last() {
836 if matches!(last_event.event_type, EventType::Scalar { .. }) {
839 let mut mapping_depth = 0;
841 let mut has_unfinished_mapping = false;
842
843 for event in self.events.iter().rev() {
844 match &event.event_type {
845 EventType::MappingEnd => mapping_depth += 1,
846 EventType::MappingStart { .. } => {
847 if mapping_depth == 0 {
848 has_unfinished_mapping = true;
849 break;
850 }
851 mapping_depth -= 1;
852 }
853 _ => {}
854 }
855 }
856
857 if has_unfinished_mapping {
858 self.state = ParserState::BlockMappingKey;
860 return Ok(());
861 }
862 }
863 }
864 }
865
866 self.events.push(Event::mapping_start(
868 token.start_position,
869 self.pending_anchor.take(),
870 self.pending_tag.take(),
871 false,
872 ));
873 self.state = ParserState::BlockMappingKey;
874 }
875 ParserState::BlockMapping | ParserState::FlowMapping => {
876 self.state = if matches!(self.state, ParserState::BlockMapping) {
878 ParserState::BlockMappingKey
879 } else {
880 ParserState::FlowMappingKey
881 };
882 }
883 ParserState::BlockMappingKey | ParserState::FlowMappingKey => {
884 }
888 _ => {
889 let context =
890 ErrorContext::from_input(self.scanner.input(), &self.position, 2)
891 .with_suggestion(
892 "Complex keys must be used in mapping contexts".to_string(),
893 );
894 return Err(Error::parse_with_context(
895 self.position,
896 "Complex key marker (?) in invalid context",
897 context,
898 ));
899 }
900 }
901 }
902 }
903
904 self.last_token_type = token_type_for_tracking;
906
907 Ok(())
908 }
909
910 #[allow(clippy::missing_const_for_fn)]
912 fn handle_node_completion(&mut self) {
913 match self.state {
914 ParserState::BlockMappingKey => {
915 }
919 ParserState::FlowMappingKey => {
920 }
924 ParserState::BlockMappingValue => {
925 self.state = ParserState::BlockMappingKey;
927 }
928 ParserState::FlowMappingValue => {
929 self.state = ParserState::FlowMapping;
931 }
932 _ => {
933 }
935 }
936 }
937}
938
939impl Default for BasicParser {
940 fn default() -> Self {
941 Self::new(String::new())
942 }
943}
944
945impl Parser for BasicParser {
946 fn check_event(&self) -> bool {
947 self.event_index < self.events.len() || self.scanner.check_token()
949 }
950
951 fn peek_event(&self) -> Result<Option<&Event>> {
952 Ok(self.events.get(self.event_index))
954 }
955
956 fn get_event(&mut self) -> Result<Option<Event>> {
957 while self.event_index >= self.events.len() && self.scanner.check_token() {
960 let events_before = self.events.len();
961 self.generate_next_event()?;
962
963 if self.events.len() == events_before && self.scanner.check_token() {
965 continue;
966 }
967 break;
968 }
969
970 if self.event_index < self.events.len() {
971 let event = self.events[self.event_index].clone();
972 self.event_index += 1;
973 Ok(Some(event))
974 } else {
975 Ok(None)
976 }
977 }
978
979 fn reset(&mut self) {
980 self.event_index = 0;
981 self.scanner.reset();
982 self.state_stack.clear();
983 self.position = Position::start();
984 self.pending_anchor = None;
985 self.pending_tag = None;
986 self.last_token_type = None;
987 }
988
989 fn position(&self) -> Position {
990 self.position
991 }
992}
993
994impl BasicParser {
995 #[allow(clippy::missing_const_for_fn)]
997 pub fn take_scanning_error(&mut self) -> Option<Error> {
998 self.scanning_error.take()
999 }
1000}
1001
1002#[cfg(test)]
1003mod tests {
1004 use super::*;
1005
1006 #[test]
1007 fn test_basic_parsing() {
1008 let mut parser = BasicParser::new_eager("42".to_string());
1009
1010 assert!(parser.check_event());
1011
1012 let event = parser.get_event().unwrap().unwrap();
1014 assert!(matches!(event.event_type, EventType::StreamStart));
1015
1016 let event = parser.get_event().unwrap().unwrap();
1018 if let EventType::DocumentStart { implicit, .. } = event.event_type {
1019 assert!(implicit);
1020 } else {
1021 panic!("Expected implicit document start");
1022 }
1023
1024 let event = parser.get_event().unwrap().unwrap();
1026 if let EventType::Scalar { value, .. } = event.event_type {
1027 assert_eq!(value, "42");
1028 } else {
1029 panic!("Expected scalar event");
1030 }
1031
1032 let event = parser.get_event().unwrap().unwrap();
1034 if let EventType::DocumentEnd { implicit } = event.event_type {
1035 assert!(implicit);
1036 } else {
1037 panic!("Expected implicit document end");
1038 }
1039
1040 let event = parser.get_event().unwrap().unwrap();
1042 assert!(matches!(event.event_type, EventType::StreamEnd));
1043 }
1044
1045 #[test]
1046 fn test_flow_sequence_parsing() {
1047 let mut parser = BasicParser::new_eager("[1, 2, 3]".to_string());
1048
1049 parser.get_event().unwrap();
1051
1052 parser.get_event().unwrap();
1054
1055 let event = parser.get_event().unwrap().unwrap();
1057 if let EventType::SequenceStart { flow_style, .. } = event.event_type {
1058 assert!(flow_style);
1059 } else {
1060 panic!("Expected flow sequence start");
1061 }
1062
1063 let event = parser.get_event().unwrap().unwrap();
1065 if let EventType::Scalar { value, .. } = event.event_type {
1066 assert_eq!(value, "1");
1067 } else {
1068 panic!("Expected scalar '1'");
1069 }
1070 }
1071
1072 #[test]
1073 fn test_flow_mapping_parsing() {
1074 let mut parser = BasicParser::new_eager("{'key': 'value'}".to_string());
1075
1076 parser.get_event().unwrap();
1078
1079 parser.get_event().unwrap();
1081
1082 let event = parser.get_event().unwrap().unwrap();
1084 if let EventType::MappingStart { flow_style, .. } = event.event_type {
1085 assert!(flow_style);
1086 } else {
1087 panic!("Expected flow mapping start");
1088 }
1089
1090 let event = parser.get_event().unwrap().unwrap();
1092 if let EventType::Scalar { value, .. } = event.event_type {
1093 assert_eq!(value, "key");
1094 } else {
1095 panic!("Expected scalar 'key'");
1096 }
1097 }
1098}