1#![allow(clippy::cast_possible_wrap)]
10#![allow(clippy::cast_sign_loss)]
11
12use alloc::{
13 borrow::{Cow, ToOwned},
14 collections::VecDeque,
15 string::String,
16 vec::Vec,
17};
18use core::char;
19
20use thiserror::Error;
21
22use crate::{
23 char_traits::{
24 as_hex, is_anchor_char, is_blank_or_breakz, is_break, is_breakz, is_flow, is_hex,
25 is_tag_char, is_uri_char,
26 },
27 input::{Input, SkipTabs},
28};
29
30#[derive(Clone, Copy, PartialEq, Debug, Eq)]
32pub enum TEncoding {
33 Utf8,
35}
36
37#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)]
39pub enum ScalarStyle {
40 Plain,
42 SingleQuoted,
44 DoubleQuoted,
46
47 Literal,
53 Folded,
60}
61
62#[derive(Clone, Copy, PartialEq, Debug, Eq, Default)]
64pub struct Marker {
65 index: usize,
67 line: usize,
69 col: usize,
71}
72
73impl Marker {
74 #[must_use]
76 pub fn new(index: usize, line: usize, col: usize) -> Marker {
77 Marker { index, line, col }
78 }
79
80 #[must_use]
82 pub fn index(&self) -> usize {
83 self.index
84 }
85
86 #[must_use]
88 pub fn line(&self) -> usize {
89 self.line
90 }
91
92 #[must_use]
94 pub fn col(&self) -> usize {
95 self.col
96 }
97}
98
99#[derive(Clone, Copy, PartialEq, Debug, Eq, Default)]
101pub struct Span {
102 pub start: Marker,
104 pub end: Marker,
106}
107
108impl Span {
109 #[must_use]
111 pub fn new(start: Marker, end: Marker) -> Span {
112 Span { start, end }
113 }
114
115 #[must_use]
122 pub fn empty(mark: Marker) -> Span {
123 Span {
124 start: mark,
125 end: mark,
126 }
127 }
128
129 #[must_use]
131 pub fn len(&self) -> usize {
132 self.end.index - self.start.index
133 }
134
135 #[must_use]
137 pub fn is_empty(&self) -> bool {
138 self.len() == 0
139 }
140}
141
142#[derive(Clone, PartialEq, Debug, Eq, Error)]
144#[error("{} at byte {} line {} column {}", .info, .mark.index, .mark.line, .mark.col + 1,)]
145pub struct ScanError {
146 mark: Marker,
148 info: String,
150}
151
152impl ScanError {
153 #[must_use]
155 pub fn new(loc: Marker, info: String) -> ScanError {
156 ScanError { mark: loc, info }
157 }
158
159 #[must_use]
161 pub fn new_str(loc: Marker, info: &str) -> ScanError {
162 ScanError {
163 mark: loc,
164 info: info.to_owned(),
165 }
166 }
167
168 #[must_use]
170 pub fn marker(&self) -> &Marker {
171 &self.mark
172 }
173
174 #[must_use]
176 pub fn info(&self) -> &str {
177 self.info.as_ref()
178 }
179}
180
181#[derive(Clone, PartialEq, Debug, Eq)]
183pub enum TokenType<'input> {
184 StreamStart(TEncoding),
186 StreamEnd,
188 VersionDirective(
190 u32,
192 u32,
194 ),
195 TagDirective(
197 Cow<'input, str>,
199 Cow<'input, str>,
201 ),
202 DocumentStart,
204 DocumentEnd,
206 BlockSequenceStart,
210 BlockMappingStart,
214 BlockEnd,
216 FlowSequenceStart,
218 FlowSequenceEnd,
220 FlowMappingStart,
222 FlowMappingEnd,
224 BlockEntry,
226 FlowEntry,
228 Key,
230 Value,
232 Alias(Cow<'input, str>),
234 Anchor(Cow<'input, str>),
236 Tag(
238 String,
240 String,
242 ),
243 Scalar(ScalarStyle, Cow<'input, str>),
245}
246
247#[derive(Clone, PartialEq, Debug, Eq)]
249pub struct Token<'input>(pub Span, pub TokenType<'input>);
250
251#[derive(Clone, PartialEq, Debug, Eq)]
286struct SimpleKey {
287 possible: bool,
300 required: bool,
308 token_number: usize,
314 mark: Marker,
316}
317
318impl SimpleKey {
319 fn new(mark: Marker) -> SimpleKey {
321 SimpleKey {
322 possible: false,
323 required: false,
324 token_number: 0,
325 mark,
326 }
327 }
328}
329
330#[derive(Clone, Debug, Default)]
332struct Indent {
333 indent: isize,
335 needs_block_end: bool,
353}
354
355#[derive(Debug, Clone, PartialEq)]
377enum ImplicitMappingState {
378 Possible,
383 Inside,
387}
388
389#[derive(Debug)]
399#[allow(clippy::struct_excessive_bools)]
400pub struct Scanner<'input, T> {
401 input: T,
405 mark: Marker,
407 tokens: VecDeque<Token<'input>>,
414 error: Option<ScanError>,
416
417 stream_start_produced: bool,
419 stream_end_produced: bool,
421 adjacent_value_allowed_at: usize,
424 simple_key_allowed: bool,
428 simple_keys: Vec<SimpleKey>,
433 indent: isize,
435 indents: Vec<Indent>,
437 flow_level: u8,
439 tokens_parsed: usize,
443 token_available: bool,
445 leading_whitespace: bool,
447 flow_mapping_started: bool,
454 implicit_flow_mapping_states: Vec<ImplicitMappingState>,
467 buf_leading_break: String,
468 buf_trailing_breaks: String,
469 buf_whitespaces: String,
470}
471
472impl<T: Input + Clone> Clone for Scanner<'_, T> {
473 fn clone(&self) -> Self {
474 Self {
475 input: self.input.clone(),
476 mark: self.mark,
477 tokens: self.tokens.clone(),
478 error: self.error.clone(),
479 stream_start_produced: self.stream_start_produced,
480 stream_end_produced: self.stream_end_produced,
481 adjacent_value_allowed_at: self.adjacent_value_allowed_at,
482 simple_key_allowed: self.simple_key_allowed,
483 simple_keys: self.simple_keys.clone(),
484 indent: self.indent,
485 indents: self.indents.clone(),
486 flow_level: self.flow_level,
487 tokens_parsed: self.tokens_parsed,
488 token_available: self.token_available,
489 leading_whitespace: self.leading_whitespace,
490 flow_mapping_started: self.flow_mapping_started,
491 implicit_flow_mapping_states: self.implicit_flow_mapping_states.clone(),
492 buf_leading_break: self.buf_leading_break.clone(),
493 buf_trailing_breaks: self.buf_trailing_breaks.clone(),
494 buf_whitespaces: self.buf_whitespaces.clone(),
495 }
496 }
497}
498
499impl<'input, T: Input> Iterator for Scanner<'input, T> {
500 type Item = Token<'input>;
501
502 fn next(&mut self) -> Option<Self::Item> {
503 if self.error.is_some() {
504 return None;
505 }
506 match self.next_token() {
507 Ok(Some(tok)) => {
508 debug_print!(
509 " \x1B[;32m\u{21B3} {:?} \x1B[;36m{:?}\x1B[;m",
510 tok.1,
511 tok.0
512 );
513 Some(tok)
514 }
515 Ok(tok) => tok,
516 Err(e) => {
517 self.error = Some(e);
518 None
519 }
520 }
521 }
522}
523
524pub type ScanResult = Result<(), ScanError>;
526
527impl<'input, T: Input> Scanner<'input, T> {
528 pub fn new(input: T) -> Self {
530 Scanner {
531 input,
532 mark: Marker::new(0, 1, 0),
533 tokens: VecDeque::new(),
534 error: None,
535
536 stream_start_produced: false,
537 stream_end_produced: false,
538 adjacent_value_allowed_at: 0,
539 simple_key_allowed: true,
540 simple_keys: Vec::new(),
541 indent: -1,
542 indents: Vec::new(),
543 flow_level: 0,
544 tokens_parsed: 0,
545 token_available: false,
546 leading_whitespace: true,
547 flow_mapping_started: false,
548 implicit_flow_mapping_states: vec![],
549
550 buf_leading_break: String::new(),
551 buf_trailing_breaks: String::new(),
552 buf_whitespaces: String::new(),
553 }
554 }
555
556 #[inline]
561 pub fn get_error(&self) -> Option<ScanError> {
562 self.error.clone()
563 }
564
565 #[inline]
567 fn skip_blank(&mut self) {
568 self.input.skip();
569
570 self.mark.index += 1;
571 self.mark.col += 1;
572 }
573
574 #[inline]
576 fn skip_non_blank(&mut self) {
577 self.input.skip();
578
579 self.mark.index += 1;
580 self.mark.col += 1;
581 self.leading_whitespace = false;
582 }
583
584 #[inline]
586 fn skip_n_non_blank(&mut self, count: usize) {
587 self.input.skip_n(count);
588
589 self.mark.index += count;
590 self.mark.col += count;
591 self.leading_whitespace = false;
592 }
593
594 #[inline]
596 fn skip_nl(&mut self) {
597 self.input.skip();
598
599 self.mark.index += 1;
600 self.mark.col = 0;
601 self.mark.line += 1;
602 self.leading_whitespace = true;
603 }
604
605 #[inline]
607 fn skip_linebreak(&mut self) {
608 if self.input.next_2_are('\r', '\n') {
609 self.skip_blank();
612 self.skip_nl();
613 } else if self.input.next_is_break() {
614 self.skip_nl();
615 }
616 }
617
618 #[inline]
620 pub fn stream_started(&self) -> bool {
621 self.stream_start_produced
622 }
623
624 #[inline]
626 pub fn stream_ended(&self) -> bool {
627 self.stream_end_produced
628 }
629
630 #[inline]
632 pub fn mark(&self) -> Marker {
633 self.mark
634 }
635
636 #[inline]
643 fn read_break(&mut self, s: &mut String) {
644 self.skip_break();
645 s.push('\n');
646 }
647
648 #[inline]
653 fn skip_break(&mut self) {
654 let c = self.input.peek();
655 let nc = self.input.peek_nth(1);
656 debug_assert!(is_break(c));
657 if c == '\r' && nc == '\n' {
658 self.skip_blank();
659 }
660 self.skip_nl();
661 }
662
663 fn insert_token(&mut self, pos: usize, tok: Token<'input>) {
665 let old_len = self.tokens.len();
666 assert!(pos <= old_len);
667 self.tokens.insert(pos, tok);
668 }
669
670 fn allow_simple_key(&mut self) {
671 self.simple_key_allowed = true;
672 }
673
674 fn disallow_simple_key(&mut self) {
675 self.simple_key_allowed = false;
676 }
677
678 pub fn fetch_next_token(&mut self) -> ScanResult {
683 self.input.lookahead(1);
684
685 if !self.stream_start_produced {
686 self.fetch_stream_start();
687 return Ok(());
688 }
689 self.skip_to_next_token()?;
690
691 debug_print!(
692 " \x1B[38;5;244m\u{2192} fetch_next_token after whitespace {:?} {:?}\x1B[m",
693 self.mark,
694 self.input.peek()
695 );
696
697 self.stale_simple_keys()?;
698
699 let mark = self.mark;
700 self.unroll_indent(mark.col as isize);
701
702 self.input.lookahead(4);
703
704 if self.input.next_is_z() {
705 self.fetch_stream_end()?;
706 return Ok(());
707 }
708
709 if self.mark.col == 0 {
710 if self.input.next_char_is('%') {
711 return self.fetch_directive();
712 } else if self.input.next_is_document_start() {
713 return self.fetch_document_indicator(TokenType::DocumentStart);
714 } else if self.input.next_is_document_end() {
715 self.fetch_document_indicator(TokenType::DocumentEnd)?;
716 self.skip_ws_to_eol(SkipTabs::Yes)?;
717 if !self.input.next_is_breakz() {
718 return Err(ScanError::new_str(
719 self.mark,
720 "invalid content after document end marker",
721 ));
722 }
723 return Ok(());
724 }
725 }
726
727 if (self.mark.col as isize) < self.indent {
728 return Err(ScanError::new_str(self.mark, "invalid indentation"));
729 }
730
731 let c = self.input.peek();
732 let nc = self.input.peek_nth(1);
733 match c {
734 '[' => self.fetch_flow_collection_start(TokenType::FlowSequenceStart),
735 '{' => self.fetch_flow_collection_start(TokenType::FlowMappingStart),
736 ']' => self.fetch_flow_collection_end(TokenType::FlowSequenceEnd),
737 '}' => self.fetch_flow_collection_end(TokenType::FlowMappingEnd),
738 ',' => self.fetch_flow_entry(),
739 '-' if is_blank_or_breakz(nc) => self.fetch_block_entry(),
740 '?' if is_blank_or_breakz(nc) => self.fetch_key(),
741 ':' if is_blank_or_breakz(nc) => self.fetch_value(),
742 ':' if self.flow_level > 0
743 && (is_flow(nc) || self.mark.index == self.adjacent_value_allowed_at) =>
744 {
745 self.fetch_flow_value()
746 }
747 '*' => self.fetch_anchor(true),
749 '&' => self.fetch_anchor(false),
751 '!' => self.fetch_tag(),
752 '|' if self.flow_level == 0 => self.fetch_block_scalar(true),
754 '>' if self.flow_level == 0 => self.fetch_block_scalar(false),
756 '\'' => self.fetch_flow_scalar(true),
757 '"' => self.fetch_flow_scalar(false),
758 '-' if !is_blank_or_breakz(nc) => self.fetch_plain_scalar(),
760 ':' | '?' if !is_blank_or_breakz(nc) && self.flow_level == 0 => {
761 self.fetch_plain_scalar()
762 }
763 '%' | '@' | '`' => Err(ScanError::new(
764 self.mark,
765 format!("unexpected character: `{c}'"),
766 )),
767 _ => self.fetch_plain_scalar(),
768 }
769 }
770
771 pub fn next_token(&mut self) -> Result<Option<Token<'input>>, ScanError> {
775 if self.stream_end_produced {
776 return Ok(None);
777 }
778
779 if !self.token_available {
780 self.fetch_more_tokens()?;
781 }
782 let Some(t) = self.tokens.pop_front() else {
783 return Err(ScanError::new_str(
784 self.mark,
785 "did not find expected next token",
786 ));
787 };
788 self.token_available = false;
789 self.tokens_parsed += 1;
790
791 if let TokenType::StreamEnd = t.1 {
792 self.stream_end_produced = true;
793 }
794 Ok(Some(t))
795 }
796
797 pub fn fetch_more_tokens(&mut self) -> ScanResult {
801 let mut need_more;
802 loop {
803 if self.tokens.is_empty() {
804 need_more = true;
805 } else {
806 need_more = false;
807 self.stale_simple_keys()?;
809 for sk in &self.simple_keys {
811 if sk.possible && sk.token_number == self.tokens_parsed {
812 need_more = true;
813 break;
814 }
815 }
816 }
817
818 if !need_more {
819 break;
820 }
821 self.fetch_next_token()?;
822 }
823 self.token_available = true;
824
825 Ok(())
826 }
827
828 fn stale_simple_keys(&mut self) -> ScanResult {
836 for sk in &mut self.simple_keys {
837 if sk.possible
838 && self.flow_level == 0
840 && (sk.mark.line < self.mark.line || sk.mark.index + 1024 < self.mark.index)
841 {
842 if sk.required {
843 return Err(ScanError::new_str(self.mark, "simple key expect ':'"));
844 }
845 sk.possible = false;
846 }
847 }
848 Ok(())
849 }
850
851 fn skip_to_next_token(&mut self) -> ScanResult {
857 loop {
858 match self.input.look_ch() {
860 '\t' if self.is_within_block()
867 && self.leading_whitespace
868 && (self.mark.col as isize) < self.indent =>
869 {
870 self.skip_ws_to_eol(SkipTabs::Yes)?;
871 if !self.input.next_is_breakz() {
873 return Err(ScanError::new_str(
874 self.mark,
875 "tabs disallowed within this context (block indentation)",
876 ));
877 }
878 }
879 '\t' | ' ' => self.skip_blank(),
880 '\n' | '\r' => {
881 self.input.lookahead(2);
882 self.skip_linebreak();
883 if self.flow_level == 0 {
884 self.allow_simple_key();
885 }
886 }
887 '#' => {
888 let comment_length = self.input.skip_while_non_breakz();
889 self.mark.index += comment_length;
890 self.mark.col += comment_length;
891 }
892 _ => break,
893 }
894 }
895 Ok(())
896 }
897
898 fn skip_yaml_whitespace(&mut self) -> ScanResult {
903 let mut need_whitespace = true;
904 loop {
905 match self.input.look_ch() {
906 ' ' => {
907 self.skip_blank();
908
909 need_whitespace = false;
910 }
911 '\n' | '\r' => {
912 self.input.lookahead(2);
913 self.skip_linebreak();
914 if self.flow_level == 0 {
915 self.allow_simple_key();
916 }
917 need_whitespace = false;
918 }
919 '#' => {
920 let comment_length = self.input.skip_while_non_breakz();
921 self.mark.index += comment_length;
922 self.mark.col += comment_length;
923 }
924 _ => break,
925 }
926 }
927
928 if need_whitespace {
929 Err(ScanError::new_str(self.mark(), "expected whitespace"))
930 } else {
931 Ok(())
932 }
933 }
934
935 fn skip_ws_to_eol(&mut self, skip_tabs: SkipTabs) -> Result<SkipTabs, ScanError> {
936 let (n_bytes, result) = self.input.skip_ws_to_eol(skip_tabs);
937 self.mark.col += n_bytes;
938 self.mark.index += n_bytes;
939 result.map_err(|msg| ScanError::new_str(self.mark, msg))
940 }
941
942 fn fetch_stream_start(&mut self) {
943 let mark = self.mark;
944 self.indent = -1;
945 self.stream_start_produced = true;
946 self.allow_simple_key();
947 self.tokens.push_back(Token(
948 Span::empty(mark),
949 TokenType::StreamStart(TEncoding::Utf8),
950 ));
951 self.simple_keys.push(SimpleKey::new(Marker::new(0, 0, 0)));
952 }
953
954 fn fetch_stream_end(&mut self) -> ScanResult {
955 if self.mark.col != 0 {
957 self.mark.col = 0;
958 self.mark.line += 1;
959 }
960
961 for sk in &mut self.simple_keys {
964 if sk.required && sk.possible {
965 return Err(ScanError::new_str(self.mark, "simple key expected"));
966 }
967 sk.possible = false;
968 }
969
970 self.unroll_indent(-1);
971 self.remove_simple_key()?;
972 self.disallow_simple_key();
973
974 self.tokens
975 .push_back(Token(Span::empty(self.mark), TokenType::StreamEnd));
976 Ok(())
977 }
978
979 fn fetch_directive(&mut self) -> ScanResult {
980 self.unroll_indent(-1);
981 self.remove_simple_key()?;
982
983 self.disallow_simple_key();
984
985 let tok = self.scan_directive()?;
986 self.tokens.push_back(tok);
987
988 Ok(())
989 }
990
991 fn scan_directive(&mut self) -> Result<Token<'input>, ScanError> {
992 let start_mark = self.mark;
993 self.skip_non_blank();
994
995 let name = self.scan_directive_name()?;
996 let tok = match name.as_ref() {
997 "YAML" => self.scan_version_directive_value(&start_mark)?,
998 "TAG" => self.scan_tag_directive_value(&start_mark)?,
999 _ => {
1001 let line_len = self.input.skip_while_non_breakz();
1003 self.mark.index += line_len;
1004 self.mark.col += line_len;
1005 Token(
1007 Span::new(start_mark, self.mark),
1008 TokenType::TagDirective(Cow::default(), Cow::default()),
1009 )
1010 }
1013 };
1014
1015 self.skip_ws_to_eol(SkipTabs::Yes)?;
1016
1017 if self.input.next_is_breakz() {
1018 self.input.lookahead(2);
1019 self.skip_linebreak();
1020 Ok(tok)
1021 } else {
1022 Err(ScanError::new_str(
1023 start_mark,
1024 "while scanning a directive, did not find expected comment or line break",
1025 ))
1026 }
1027 }
1028
1029 fn scan_version_directive_value(&mut self, mark: &Marker) -> Result<Token<'input>, ScanError> {
1030 let n_blanks = self.input.skip_while_blank();
1031 self.mark.index += n_blanks;
1032 self.mark.col += n_blanks;
1033
1034 let major = self.scan_version_directive_number(mark)?;
1035
1036 if self.input.peek() != '.' {
1037 return Err(ScanError::new_str(
1038 *mark,
1039 "while scanning a YAML directive, did not find expected digit or '.' character",
1040 ));
1041 }
1042 self.skip_non_blank();
1043
1044 let minor = self.scan_version_directive_number(mark)?;
1045
1046 Ok(Token(
1047 Span::new(*mark, self.mark),
1048 TokenType::VersionDirective(major, minor),
1049 ))
1050 }
1051
1052 fn scan_directive_name(&mut self) -> Result<String, ScanError> {
1053 let start_mark = self.mark;
1054 let mut string = String::new();
1055
1056 let n_chars = self.input.fetch_while_is_alpha(&mut string);
1057 self.mark.index += n_chars;
1058 self.mark.col += n_chars;
1059
1060 if string.is_empty() {
1061 return Err(ScanError::new_str(
1062 start_mark,
1063 "while scanning a directive, could not find expected directive name",
1064 ));
1065 }
1066
1067 if !is_blank_or_breakz(self.input.peek()) {
1068 return Err(ScanError::new_str(
1069 start_mark,
1070 "while scanning a directive, found unexpected non-alphabetical character",
1071 ));
1072 }
1073
1074 Ok(string)
1075 }
1076
1077 fn scan_version_directive_number(&mut self, mark: &Marker) -> Result<u32, ScanError> {
1078 let mut val = 0u32;
1079 let mut length = 0usize;
1080 while let Some(digit) = self.input.look_ch().to_digit(10) {
1081 if length + 1 > 9 {
1082 return Err(ScanError::new_str(
1083 *mark,
1084 "while scanning a YAML directive, found extremely long version number",
1085 ));
1086 }
1087 length += 1;
1088 val = val * 10 + digit;
1089 self.skip_non_blank();
1090 }
1091
1092 if length == 0 {
1093 return Err(ScanError::new_str(
1094 *mark,
1095 "while scanning a YAML directive, did not find expected version number",
1096 ));
1097 }
1098
1099 Ok(val)
1100 }
1101
1102 fn scan_tag_directive_value(&mut self, mark: &Marker) -> Result<Token<'input>, ScanError> {
1103 let n_blanks = self.input.skip_while_blank();
1104 self.mark.index += n_blanks;
1105 self.mark.col += n_blanks;
1106
1107 let handle = self.scan_tag_handle(true, mark)?;
1108
1109 let n_blanks = self.input.skip_while_blank();
1110 self.mark.index += n_blanks;
1111 self.mark.col += n_blanks;
1112
1113 let prefix = self.scan_tag_prefix(mark)?;
1114
1115 self.input.lookahead(1);
1116
1117 if self.input.next_is_blank_or_breakz() {
1118 Ok(Token(
1119 Span::new(*mark, self.mark),
1120 TokenType::TagDirective(handle.into(), prefix.into()),
1121 ))
1122 } else {
1123 Err(ScanError::new_str(
1124 *mark,
1125 "while scanning TAG, did not find expected whitespace or line break",
1126 ))
1127 }
1128 }
1129
1130 fn fetch_tag(&mut self) -> ScanResult {
1131 self.save_simple_key();
1132 self.disallow_simple_key();
1133
1134 let tok = self.scan_tag()?;
1135 self.tokens.push_back(tok);
1136 Ok(())
1137 }
1138
1139 fn scan_tag(&mut self) -> Result<Token<'input>, ScanError> {
1140 let start_mark = self.mark;
1141 let mut handle = String::new();
1142 let mut suffix;
1143
1144 self.input.lookahead(2);
1146
1147 if self.input.nth_char_is(1, '<') {
1148 suffix = self.scan_verbatim_tag(&start_mark)?;
1149 } else {
1150 handle = self.scan_tag_handle(false, &start_mark)?;
1152 if handle.len() >= 2 && handle.starts_with('!') && handle.ends_with('!') {
1154 let is_secondary_handle = handle == "!!";
1156 suffix =
1157 self.scan_tag_shorthand_suffix(false, is_secondary_handle, "", &start_mark)?;
1158 } else {
1159 suffix = self.scan_tag_shorthand_suffix(false, false, &handle, &start_mark)?;
1160 "!".clone_into(&mut handle);
1161 if suffix.is_empty() {
1164 handle.clear();
1165 "!".clone_into(&mut suffix);
1166 }
1167 }
1168 }
1169
1170 if is_blank_or_breakz(self.input.look_ch())
1171 || (self.flow_level > 0 && self.input.next_is_flow())
1172 {
1173 Ok(Token(
1175 Span::new(start_mark, self.mark),
1176 TokenType::Tag(handle, suffix),
1177 ))
1178 } else {
1179 Err(ScanError::new_str(
1180 start_mark,
1181 "while scanning a tag, did not find expected whitespace or line break",
1182 ))
1183 }
1184 }
1185
1186 fn scan_tag_handle(&mut self, directive: bool, mark: &Marker) -> Result<String, ScanError> {
1187 let mut string = String::new();
1188 if self.input.look_ch() != '!' {
1189 return Err(ScanError::new_str(
1190 *mark,
1191 "while scanning a tag, did not find expected '!'",
1192 ));
1193 }
1194
1195 string.push(self.input.peek());
1196 self.skip_non_blank();
1197
1198 let n_chars = self.input.fetch_while_is_alpha(&mut string);
1199 self.mark.index += n_chars;
1200 self.mark.col += n_chars;
1201
1202 if self.input.peek() == '!' {
1204 string.push(self.input.peek());
1205 self.skip_non_blank();
1206 } else if directive && string != "!" {
1207 return Err(ScanError::new_str(
1211 *mark,
1212 "while parsing a tag directive, did not find expected '!'",
1213 ));
1214 }
1215 Ok(string)
1216 }
1217
1218 fn scan_tag_prefix(&mut self, start_mark: &Marker) -> Result<String, ScanError> {
1224 let mut string = String::new();
1225
1226 if self.input.look_ch() == '!' {
1227 string.push(self.input.peek());
1229 self.skip_non_blank();
1230 } else if !is_tag_char(self.input.peek()) {
1231 return Err(ScanError::new_str(
1233 *start_mark,
1234 "invalid global tag character",
1235 ));
1236 } else if self.input.peek() == '%' {
1237 string.push(self.scan_uri_escapes(start_mark)?);
1239 } else {
1240 string.push(self.input.peek());
1242 self.skip_non_blank();
1243 }
1244
1245 while is_uri_char(self.input.look_ch()) {
1246 if self.input.peek() == '%' {
1247 string.push(self.scan_uri_escapes(start_mark)?);
1248 } else {
1249 string.push(self.input.peek());
1250 self.skip_non_blank();
1251 }
1252 }
1253
1254 Ok(string)
1255 }
1256
1257 fn scan_verbatim_tag(&mut self, start_mark: &Marker) -> Result<String, ScanError> {
1261 self.skip_non_blank();
1263 self.skip_non_blank();
1264
1265 let mut string = String::new();
1266 while is_uri_char(self.input.look_ch()) {
1267 if self.input.peek() == '%' {
1268 string.push(self.scan_uri_escapes(start_mark)?);
1269 } else {
1270 string.push(self.input.peek());
1271 self.skip_non_blank();
1272 }
1273 }
1274
1275 if self.input.peek() != '>' {
1276 return Err(ScanError::new_str(
1277 *start_mark,
1278 "while scanning a verbatim tag, did not find the expected '>'",
1279 ));
1280 }
1281 self.skip_non_blank();
1282
1283 Ok(string)
1284 }
1285
1286 fn scan_tag_shorthand_suffix(
1287 &mut self,
1288 _directive: bool,
1289 _is_secondary: bool,
1290 head: &str,
1291 mark: &Marker,
1292 ) -> Result<String, ScanError> {
1293 let mut length = head.len();
1294 let mut string = String::new();
1295
1296 if length > 1 {
1299 string.extend(head.chars().skip(1));
1300 }
1301
1302 while is_tag_char(self.input.look_ch()) {
1303 if self.input.peek() == '%' {
1305 string.push(self.scan_uri_escapes(mark)?);
1306 } else {
1307 string.push(self.input.peek());
1308 self.skip_non_blank();
1309 }
1310
1311 length += 1;
1312 }
1313
1314 if length == 0 {
1315 return Err(ScanError::new_str(
1316 *mark,
1317 "while parsing a tag, did not find expected tag URI",
1318 ));
1319 }
1320
1321 Ok(string)
1322 }
1323
1324 fn scan_uri_escapes(&mut self, mark: &Marker) -> Result<char, ScanError> {
1325 let mut width = 0usize;
1326 let mut code = 0u32;
1327 loop {
1328 self.input.lookahead(3);
1329
1330 let c = self.input.peek_nth(1);
1331 let nc = self.input.peek_nth(2);
1332
1333 if !(self.input.peek() == '%' && is_hex(c) && is_hex(nc)) {
1334 return Err(ScanError::new_str(
1335 *mark,
1336 "while parsing a tag, found an invalid escape sequence",
1337 ));
1338 }
1339
1340 let byte = (as_hex(c) << 4) + as_hex(nc);
1341 if width == 0 {
1342 width = match byte {
1343 _ if byte & 0x80 == 0x00 => 1,
1344 _ if byte & 0xE0 == 0xC0 => 2,
1345 _ if byte & 0xF0 == 0xE0 => 3,
1346 _ if byte & 0xF8 == 0xF0 => 4,
1347 _ => {
1348 return Err(ScanError::new_str(
1349 *mark,
1350 "while parsing a tag, found an incorrect leading UTF-8 byte",
1351 ));
1352 }
1353 };
1354 code = byte;
1355 } else {
1356 if byte & 0xc0 != 0x80 {
1357 return Err(ScanError::new_str(
1358 *mark,
1359 "while parsing a tag, found an incorrect trailing UTF-8 byte",
1360 ));
1361 }
1362 code = (code << 8) + byte;
1363 }
1364
1365 self.skip_n_non_blank(3);
1366
1367 width -= 1;
1368 if width == 0 {
1369 break;
1370 }
1371 }
1372
1373 match char::from_u32(code) {
1374 Some(ch) => Ok(ch),
1375 None => Err(ScanError::new_str(
1376 *mark,
1377 "while parsing a tag, found an invalid UTF-8 codepoint",
1378 )),
1379 }
1380 }
1381
1382 fn fetch_anchor(&mut self, alias: bool) -> ScanResult {
1383 self.save_simple_key();
1384 self.disallow_simple_key();
1385
1386 let tok = self.scan_anchor(alias)?;
1387
1388 self.tokens.push_back(tok);
1389
1390 Ok(())
1391 }
1392
1393 fn scan_anchor(&mut self, alias: bool) -> Result<Token<'input>, ScanError> {
1394 let mut string = String::new();
1395 let start_mark = self.mark;
1396
1397 self.skip_non_blank();
1398 while is_anchor_char(self.input.look_ch()) {
1399 string.push(self.input.peek());
1400 self.skip_non_blank();
1401 }
1402
1403 if string.is_empty() {
1404 return Err(ScanError::new_str(
1405 start_mark,
1406 "while scanning an anchor or alias, did not find expected alphabetic or numeric character",
1407 ));
1408 }
1409
1410 let tok = if alias {
1411 TokenType::Alias(string.into())
1412 } else {
1413 TokenType::Anchor(string.into())
1414 };
1415 Ok(Token(Span::new(start_mark, self.mark), tok))
1416 }
1417
1418 fn fetch_flow_collection_start(&mut self, tok: TokenType<'input>) -> ScanResult {
1419 self.save_simple_key();
1421
1422 self.roll_one_col_indent();
1423 self.increase_flow_level()?;
1424
1425 self.allow_simple_key();
1426
1427 let start_mark = self.mark;
1428 self.skip_non_blank();
1429
1430 if tok == TokenType::FlowMappingStart {
1431 self.flow_mapping_started = true;
1432 } else {
1433 self.implicit_flow_mapping_states
1434 .push(ImplicitMappingState::Possible);
1435 }
1436
1437 self.skip_ws_to_eol(SkipTabs::Yes)?;
1438
1439 self.tokens
1440 .push_back(Token(Span::new(start_mark, self.mark), tok));
1441 Ok(())
1442 }
1443
1444 fn fetch_flow_collection_end(&mut self, tok: TokenType<'input>) -> ScanResult {
1445 if self.flow_level == 0 {
1447 return Err(ScanError::new_str(self.mark, "misplaced bracket"));
1448 }
1449
1450 self.remove_simple_key()?;
1451 self.decrease_flow_level();
1452
1453 self.disallow_simple_key();
1454
1455 if matches!(tok, TokenType::FlowSequenceEnd) {
1456 self.end_implicit_mapping(self.mark);
1457 self.implicit_flow_mapping_states.pop();
1459 }
1460
1461 let start_mark = self.mark;
1462 self.skip_non_blank();
1463 self.skip_ws_to_eol(SkipTabs::Yes)?;
1464
1465 if self.flow_level > 0 {
1471 self.adjacent_value_allowed_at = self.mark.index;
1472 }
1473
1474 self.tokens
1475 .push_back(Token(Span::new(start_mark, self.mark), tok));
1476 Ok(())
1477 }
1478
1479 fn fetch_flow_entry(&mut self) -> ScanResult {
1481 self.remove_simple_key()?;
1482 self.allow_simple_key();
1483
1484 self.end_implicit_mapping(self.mark);
1485
1486 let start_mark = self.mark;
1487 self.skip_non_blank();
1488 self.skip_ws_to_eol(SkipTabs::Yes)?;
1489
1490 self.tokens.push_back(Token(
1491 Span::new(start_mark, self.mark),
1492 TokenType::FlowEntry,
1493 ));
1494 Ok(())
1495 }
1496
1497 fn increase_flow_level(&mut self) -> ScanResult {
1498 self.simple_keys.push(SimpleKey::new(Marker::new(0, 0, 0)));
1499 self.flow_level = self
1500 .flow_level
1501 .checked_add(1)
1502 .ok_or_else(|| ScanError::new_str(self.mark, "recursion limit exceeded"))?;
1503 Ok(())
1504 }
1505
1506 fn decrease_flow_level(&mut self) {
1507 if self.flow_level > 0 {
1508 self.flow_level -= 1;
1509 self.simple_keys.pop().unwrap();
1510 }
1511 }
1512
1513 fn fetch_block_entry(&mut self) -> ScanResult {
1519 if self.flow_level > 0 {
1520 return Err(ScanError::new_str(
1522 self.mark,
1523 r#""-" is only valid inside a block"#,
1524 ));
1525 }
1526 if !self.simple_key_allowed {
1528 return Err(ScanError::new_str(
1529 self.mark,
1530 "block sequence entries are not allowed in this context",
1531 ));
1532 }
1533
1534 if let Some(Token(span, TokenType::Anchor(..) | TokenType::Tag(..))) = self.tokens.back() {
1536 if self.mark.col == 0 && span.start.col == 0 && self.indent > -1 {
1537 return Err(ScanError::new_str(
1538 span.start,
1539 "invalid indentation for anchor",
1540 ));
1541 }
1542 }
1543
1544 let mark = self.mark;
1546 self.skip_non_blank();
1547
1548 self.roll_indent(mark.col, None, TokenType::BlockSequenceStart, mark);
1550 let found_tabs = self.skip_ws_to_eol(SkipTabs::Yes)?.found_tabs();
1551 self.input.lookahead(2);
1552 if found_tabs && self.input.next_char_is('-') && is_blank_or_breakz(self.input.peek_nth(1))
1553 {
1554 return Err(ScanError::new_str(
1555 self.mark,
1556 "'-' must be followed by a valid YAML whitespace",
1557 ));
1558 }
1559
1560 self.skip_ws_to_eol(SkipTabs::No)?;
1561 self.input.lookahead(1);
1562 if self.input.next_is_break() || self.input.next_is_flow() {
1563 self.roll_one_col_indent();
1564 }
1565
1566 self.remove_simple_key()?;
1567 self.allow_simple_key();
1568
1569 self.tokens
1570 .push_back(Token(Span::empty(self.mark), TokenType::BlockEntry));
1571
1572 Ok(())
1573 }
1574
1575 fn fetch_document_indicator(&mut self, t: TokenType<'input>) -> ScanResult {
1576 self.unroll_indent(-1);
1577 self.remove_simple_key()?;
1578 self.disallow_simple_key();
1579
1580 let mark = self.mark;
1581
1582 self.skip_n_non_blank(3);
1583
1584 self.tokens.push_back(Token(Span::new(mark, self.mark), t));
1585 Ok(())
1586 }
1587
1588 fn fetch_block_scalar(&mut self, literal: bool) -> ScanResult {
1589 self.save_simple_key();
1590 self.allow_simple_key();
1591 let tok = self.scan_block_scalar(literal)?;
1592
1593 self.tokens.push_back(tok);
1594 Ok(())
1595 }
1596
1597 #[allow(clippy::too_many_lines)]
1598 fn scan_block_scalar(&mut self, literal: bool) -> Result<Token<'input>, ScanError> {
1599 let start_mark = self.mark;
1600 let mut chomping = Chomping::Clip;
1601 let mut increment: usize = 0;
1602 let mut indent: usize = 0;
1603 let mut trailing_blank: bool;
1604 let mut leading_blank: bool = false;
1605 let style = if literal {
1606 ScalarStyle::Literal
1607 } else {
1608 ScalarStyle::Folded
1609 };
1610
1611 let mut string = String::new();
1612 let mut leading_break = String::new();
1613 let mut trailing_breaks = String::new();
1614 let mut chomping_break = String::new();
1615
1616 self.skip_non_blank();
1618 self.unroll_non_block_indents();
1619
1620 if self.input.look_ch() == '+' || self.input.peek() == '-' {
1621 if self.input.peek() == '+' {
1622 chomping = Chomping::Keep;
1623 } else {
1624 chomping = Chomping::Strip;
1625 }
1626 self.skip_non_blank();
1627 self.input.lookahead(1);
1628 if self.input.next_is_digit() {
1629 if self.input.peek() == '0' {
1630 return Err(ScanError::new_str(
1631 start_mark,
1632 "while scanning a block scalar, found an indentation indicator equal to 0",
1633 ));
1634 }
1635 increment = (self.input.peek() as usize) - ('0' as usize);
1636 self.skip_non_blank();
1637 }
1638 } else if self.input.next_is_digit() {
1639 if self.input.peek() == '0' {
1640 return Err(ScanError::new_str(
1641 start_mark,
1642 "while scanning a block scalar, found an indentation indicator equal to 0",
1643 ));
1644 }
1645
1646 increment = (self.input.peek() as usize) - ('0' as usize);
1647 self.skip_non_blank();
1648 self.input.lookahead(1);
1649 if self.input.peek() == '+' || self.input.peek() == '-' {
1650 if self.input.peek() == '+' {
1651 chomping = Chomping::Keep;
1652 } else {
1653 chomping = Chomping::Strip;
1654 }
1655 self.skip_non_blank();
1656 }
1657 }
1658
1659 self.skip_ws_to_eol(SkipTabs::Yes)?;
1660
1661 self.input.lookahead(1);
1663 if !self.input.next_is_breakz() {
1664 return Err(ScanError::new_str(
1665 start_mark,
1666 "while scanning a block scalar, did not find expected comment or line break",
1667 ));
1668 }
1669
1670 if self.input.next_is_break() {
1671 self.input.lookahead(2);
1672 self.read_break(&mut chomping_break);
1673 }
1674
1675 if self.input.look_ch() == '\t' {
1676 return Err(ScanError::new_str(
1677 start_mark,
1678 "a block scalar content cannot start with a tab",
1679 ));
1680 }
1681
1682 if increment > 0 {
1683 indent = if self.indent >= 0 {
1684 (self.indent + increment as isize) as usize
1685 } else {
1686 increment
1687 }
1688 }
1689
1690 if indent == 0 {
1692 self.skip_block_scalar_first_line_indent(&mut indent, &mut trailing_breaks);
1693 } else {
1694 self.skip_block_scalar_indent(indent, &mut trailing_breaks);
1695 }
1696
1697 if self.input.next_is_z() {
1702 let contents = match chomping {
1703 Chomping::Strip => String::new(),
1705 _ if self.mark.line == start_mark.line() => String::new(),
1707 Chomping::Clip => chomping_break,
1710 Chomping::Keep if trailing_breaks.is_empty() => chomping_break,
1713 Chomping::Keep => trailing_breaks,
1715 };
1716 return Ok(Token(
1717 Span::new(start_mark, self.mark),
1718 TokenType::Scalar(style, contents.into()),
1719 ));
1720 }
1721
1722 if self.mark.col < indent && (self.mark.col as isize) > self.indent {
1723 return Err(ScanError::new_str(
1724 self.mark,
1725 "wrongly indented line in block scalar",
1726 ));
1727 }
1728
1729 let mut line_buffer = String::with_capacity(100);
1730 let start_mark = self.mark;
1731 while self.mark.col == indent && !self.input.next_is_z() {
1732 if indent == 0 {
1733 self.input.lookahead(4);
1734 if self.input.next_is_document_end() {
1735 break;
1736 }
1737 }
1738
1739 trailing_blank = self.input.next_is_blank();
1741 if !literal && !leading_break.is_empty() && !leading_blank && !trailing_blank {
1742 string.push_str(&trailing_breaks);
1743 if trailing_breaks.is_empty() {
1744 string.push(' ');
1745 }
1746 } else {
1747 string.push_str(&leading_break);
1748 string.push_str(&trailing_breaks);
1749 }
1750
1751 leading_break.clear();
1752 trailing_breaks.clear();
1753
1754 leading_blank = self.input.next_is_blank();
1755
1756 self.scan_block_scalar_content_line(&mut string, &mut line_buffer);
1757
1758 self.input.lookahead(2);
1760 if self.input.next_is_z() {
1761 break;
1762 }
1763
1764 self.read_break(&mut leading_break);
1765
1766 self.skip_block_scalar_indent(indent, &mut trailing_breaks);
1768 }
1769
1770 if chomping != Chomping::Strip {
1772 string.push_str(&leading_break);
1773 if self.input.next_is_z() && self.mark.col >= indent.max(1) {
1777 string.push('\n');
1778 }
1779 }
1780
1781 if chomping == Chomping::Keep {
1782 string.push_str(&trailing_breaks);
1783 }
1784
1785 Ok(Token(
1786 Span::new(start_mark, self.mark),
1787 TokenType::Scalar(style, string.into()),
1788 ))
1789 }
1790
1791 fn scan_block_scalar_content_line(&mut self, string: &mut String, line_buffer: &mut String) {
1801 while !self.input.buf_is_empty() && !self.input.next_is_breakz() {
1803 string.push(self.input.peek());
1804 self.skip_blank();
1810 }
1811
1812 if self.input.buf_is_empty() {
1815 while let Some(c) = self.input.raw_read_non_breakz_ch() {
1821 line_buffer.push(c);
1822 }
1823
1824 let n_chars = line_buffer.chars().count();
1826 self.mark.col += n_chars;
1827 self.mark.index += n_chars;
1828
1829 string.reserve(line_buffer.len());
1831 string.push_str(line_buffer);
1832 line_buffer.clear();
1834 }
1835 }
1836
1837 fn skip_block_scalar_indent(&mut self, indent: usize, breaks: &mut String) {
1839 loop {
1840 if indent < self.input.bufmaxlen() - 2 {
1842 self.input.lookahead(self.input.bufmaxlen());
1843 while self.mark.col < indent && self.input.peek() == ' ' {
1844 self.skip_blank();
1845 }
1846 } else {
1847 loop {
1848 self.input.lookahead(self.input.bufmaxlen());
1849 while !self.input.buf_is_empty()
1850 && self.mark.col < indent
1851 && self.input.peek() == ' '
1852 {
1853 self.skip_blank();
1854 }
1855 if self.mark.col == indent
1859 || (!self.input.buf_is_empty() && self.input.peek() != ' ')
1860 {
1861 break;
1862 }
1863 }
1864 self.input.lookahead(2);
1865 }
1866
1867 if self.input.next_is_break() {
1869 self.read_break(breaks);
1870 } else {
1871 break;
1873 }
1874 }
1875 }
1876
1877 fn skip_block_scalar_first_line_indent(&mut self, indent: &mut usize, breaks: &mut String) {
1882 let mut max_indent = 0;
1883 loop {
1884 while self.input.look_ch() == ' ' {
1886 self.skip_blank();
1887 }
1888
1889 if self.mark.col > max_indent {
1890 max_indent = self.mark.col;
1891 }
1892
1893 if self.input.next_is_break() {
1894 self.input.lookahead(2);
1896 self.read_break(breaks);
1897 } else {
1898 break;
1900 }
1901 }
1902
1903 *indent = max_indent.max((self.indent + 1) as usize);
1912 if self.indent > 0 {
1913 *indent = (*indent).max(1);
1914 }
1915 }
1916
1917 fn fetch_flow_scalar(&mut self, single: bool) -> ScanResult {
1918 self.save_simple_key();
1919 self.disallow_simple_key();
1920
1921 let tok = self.scan_flow_scalar(single)?;
1922
1923 self.skip_to_next_token()?;
1926 self.adjacent_value_allowed_at = self.mark.index;
1927
1928 self.tokens.push_back(tok);
1929 Ok(())
1930 }
1931
1932 #[allow(clippy::too_many_lines)]
1933 fn scan_flow_scalar(&mut self, single: bool) -> Result<Token<'input>, ScanError> {
1934 let start_mark = self.mark;
1935
1936 let mut string = String::new();
1937 let mut leading_break = String::new();
1938 let mut trailing_breaks = String::new();
1939 let mut whitespaces = String::new();
1940 let mut leading_blanks;
1941
1942 self.skip_non_blank();
1944
1945 loop {
1946 self.input.lookahead(4);
1948
1949 if self.mark.col == 0 && self.input.next_is_document_indicator() {
1950 return Err(ScanError::new_str(
1951 start_mark,
1952 "while scanning a quoted scalar, found unexpected document indicator",
1953 ));
1954 }
1955
1956 if self.input.next_is_z() {
1957 return Err(ScanError::new_str(
1958 start_mark,
1959 "while scanning a quoted scalar, found unexpected end of stream",
1960 ));
1961 }
1962
1963 if (self.mark.col as isize) < self.indent {
1964 return Err(ScanError::new_str(
1965 start_mark,
1966 "invalid indentation in quoted scalar",
1967 ));
1968 }
1969
1970 leading_blanks = false;
1971 self.consume_flow_scalar_non_whitespace_chars(
1972 single,
1973 &mut string,
1974 &mut leading_blanks,
1975 &start_mark,
1976 )?;
1977
1978 match self.input.look_ch() {
1979 '\'' if single => break,
1980 '"' if !single => break,
1981 _ => {}
1982 }
1983
1984 while self.input.next_is_blank() || self.input.next_is_break() {
1986 if self.input.next_is_blank() {
1987 if leading_blanks {
1989 if self.input.peek() == '\t' && (self.mark.col as isize) < self.indent {
1990 return Err(ScanError::new_str(
1991 self.mark,
1992 "tab cannot be used as indentation",
1993 ));
1994 }
1995 self.skip_blank();
1996 } else {
1997 whitespaces.push(self.input.peek());
1998 self.skip_blank();
1999 }
2000 } else {
2001 self.input.lookahead(2);
2002 if leading_blanks {
2004 self.read_break(&mut trailing_breaks);
2005 } else {
2006 whitespaces.clear();
2007 self.read_break(&mut leading_break);
2008 leading_blanks = true;
2009 }
2010 }
2011 self.input.lookahead(1);
2012 }
2013
2014 if leading_blanks {
2016 if leading_break.is_empty() {
2017 string.push_str(&leading_break);
2018 string.push_str(&trailing_breaks);
2019 trailing_breaks.clear();
2020 leading_break.clear();
2021 } else {
2022 if trailing_breaks.is_empty() {
2023 string.push(' ');
2024 } else {
2025 string.push_str(&trailing_breaks);
2026 trailing_breaks.clear();
2027 }
2028 leading_break.clear();
2029 }
2030 } else {
2031 string.push_str(&whitespaces);
2032 whitespaces.clear();
2033 }
2034 } self.skip_non_blank();
2038 self.skip_ws_to_eol(SkipTabs::Yes)?;
2040 match self.input.peek() {
2041 ',' | '}' | ']' if self.flow_level > 0 => {}
2043 c if is_breakz(c) => {}
2045 ':' if self.flow_level == 0 && start_mark.line == self.mark.line => {}
2048 ':' if self.flow_level > 0 => {}
2050 _ => {
2051 return Err(ScanError::new_str(
2052 self.mark,
2053 "invalid trailing content after double-quoted scalar",
2054 ));
2055 }
2056 }
2057
2058 let style = if single {
2059 ScalarStyle::SingleQuoted
2060 } else {
2061 ScalarStyle::DoubleQuoted
2062 };
2063 Ok(Token(
2064 Span::new(start_mark, self.mark),
2065 TokenType::Scalar(style, string.into()),
2066 ))
2067 }
2068
2069 fn consume_flow_scalar_non_whitespace_chars(
2078 &mut self,
2079 single: bool,
2080 string: &mut String,
2081 leading_blanks: &mut bool,
2082 start_mark: &Marker,
2083 ) -> Result<(), ScanError> {
2084 self.input.lookahead(2);
2085 while !is_blank_or_breakz(self.input.peek()) {
2086 match self.input.peek() {
2087 '\'' if self.input.peek_nth(1) == '\'' && single => {
2089 string.push('\'');
2090 self.skip_n_non_blank(2);
2091 }
2092 '\'' if single => break,
2094 '"' if !single => break,
2095 '\\' if !single && is_break(self.input.peek_nth(1)) => {
2097 self.input.lookahead(3);
2098 self.skip_non_blank();
2099 self.skip_linebreak();
2100 *leading_blanks = true;
2101 break;
2102 }
2103 '\\' if !single => {
2105 string.push(self.resolve_flow_scalar_escape_sequence(start_mark)?);
2106 }
2107 c => {
2108 string.push(c);
2109 self.skip_non_blank();
2110 }
2111 }
2112 self.input.lookahead(2);
2113 }
2114 Ok(())
2115 }
2116
2117 fn resolve_flow_scalar_escape_sequence(
2124 &mut self,
2125 start_mark: &Marker,
2126 ) -> Result<char, ScanError> {
2127 let mut code_length = 0usize;
2128 let mut ret = '\0';
2129
2130 match self.input.peek_nth(1) {
2131 '0' => ret = '\0',
2132 'a' => ret = '\x07',
2133 'b' => ret = '\x08',
2134 't' | '\t' => ret = '\t',
2135 'n' => ret = '\n',
2136 'v' => ret = '\x0b',
2137 'f' => ret = '\x0c',
2138 'r' => ret = '\x0d',
2139 'e' => ret = '\x1b',
2140 ' ' => ret = '\x20',
2141 '"' => ret = '"',
2142 '/' => ret = '/',
2143 '\\' => ret = '\\',
2144 'N' => ret = char::from_u32(0x85).unwrap(),
2146 '_' => ret = char::from_u32(0xA0).unwrap(),
2148 'L' => ret = char::from_u32(0x2028).unwrap(),
2150 'P' => ret = char::from_u32(0x2029).unwrap(),
2152 'x' => code_length = 2,
2153 'u' => code_length = 4,
2154 'U' => code_length = 8,
2155 _ => {
2156 return Err(ScanError::new_str(
2157 *start_mark,
2158 "while parsing a quoted scalar, found unknown escape character",
2159 ));
2160 }
2161 }
2162 self.skip_n_non_blank(2);
2163
2164 if code_length > 0 {
2166 self.input.lookahead(code_length);
2167 let mut value = 0u32;
2168 for i in 0..code_length {
2169 let c = self.input.peek_nth(i);
2170 if !is_hex(c) {
2171 return Err(ScanError::new_str(
2172 *start_mark,
2173 "while parsing a quoted scalar, did not find expected hexadecimal number",
2174 ));
2175 }
2176 value = (value << 4) + as_hex(c);
2177 }
2178
2179 let Some(ch) = char::from_u32(value) else {
2180 return Err(ScanError::new_str(
2181 *start_mark,
2182 "while parsing a quoted scalar, found invalid Unicode character escape code",
2183 ));
2184 };
2185 ret = ch;
2186
2187 self.skip_n_non_blank(code_length);
2188 }
2189 Ok(ret)
2190 }
2191
2192 fn fetch_plain_scalar(&mut self) -> ScanResult {
2193 self.save_simple_key();
2194 self.disallow_simple_key();
2195
2196 let tok = self.scan_plain_scalar()?;
2197
2198 self.tokens.push_back(tok);
2199 Ok(())
2200 }
2201
2202 #[allow(clippy::too_many_lines)]
2207 fn scan_plain_scalar(&mut self) -> Result<Token<'input>, ScanError> {
2208 self.unroll_non_block_indents();
2209 let indent = self.indent + 1;
2210 let start_mark = self.mark;
2211
2212 if self.flow_level > 0 && (start_mark.col as isize) < indent {
2213 return Err(ScanError::new_str(
2214 start_mark,
2215 "invalid indentation in flow construct",
2216 ));
2217 }
2218
2219 let mut string = String::with_capacity(32);
2220 self.buf_whitespaces.clear();
2221 self.buf_leading_break.clear();
2222 self.buf_trailing_breaks.clear();
2223 let mut end_mark = self.mark;
2224
2225 loop {
2226 self.input.lookahead(4);
2227 if (self.mark.col == 0 && self.input.next_is_document_indicator())
2228 || self.input.peek() == '#'
2229 {
2230 break;
2231 }
2232
2233 if self.flow_level > 0 && self.input.peek() == '-' && is_flow(self.input.peek_nth(1)) {
2234 return Err(ScanError::new_str(
2235 self.mark,
2236 "plain scalar cannot start with '-' followed by ,[]{}",
2237 ));
2238 }
2239
2240 if !self.input.next_is_blank_or_breakz()
2241 && self.input.next_can_be_plain_scalar(self.flow_level > 0)
2242 {
2243 if self.leading_whitespace {
2244 if self.buf_leading_break.is_empty() {
2245 string.push_str(&self.buf_leading_break);
2246 string.push_str(&self.buf_trailing_breaks);
2247 self.buf_trailing_breaks.clear();
2248 self.buf_leading_break.clear();
2249 } else {
2250 if self.buf_trailing_breaks.is_empty() {
2251 string.push(' ');
2252 } else {
2253 string.push_str(&self.buf_trailing_breaks);
2254 self.buf_trailing_breaks.clear();
2255 }
2256 self.buf_leading_break.clear();
2257 }
2258 self.leading_whitespace = false;
2259 } else if !self.buf_whitespaces.is_empty() {
2260 string.push_str(&self.buf_whitespaces);
2261 self.buf_whitespaces.clear();
2262 }
2263
2264 string.push(self.input.peek());
2266 self.skip_non_blank();
2267 string.reserve(self.input.bufmaxlen());
2268
2269 let mut end = false;
2271 while !end {
2272 self.input.lookahead(self.input.bufmaxlen());
2276 for _ in 0..self.input.bufmaxlen() - 1 {
2277 if self.input.next_is_blank_or_breakz()
2278 || !self.input.next_can_be_plain_scalar(self.flow_level > 0)
2279 {
2280 end = true;
2281 break;
2282 }
2283 string.push(self.input.peek());
2284 self.skip_non_blank();
2285 }
2286 }
2287 end_mark = self.mark;
2288 }
2289
2290 if !(self.input.next_is_blank() || self.input.next_is_break()) {
2295 break;
2296 }
2297
2298 self.input.lookahead(2);
2300 while self.input.next_is_blank_or_break() {
2301 if self.input.next_is_blank() {
2302 if !self.leading_whitespace {
2303 self.buf_whitespaces.push(self.input.peek());
2304 self.skip_blank();
2305 } else if (self.mark.col as isize) < indent && self.input.peek() == '\t' {
2306 self.skip_ws_to_eol(SkipTabs::Yes)?;
2309 if !self.input.next_is_breakz() {
2310 return Err(ScanError::new_str(
2311 start_mark,
2312 "while scanning a plain scalar, found a tab",
2313 ));
2314 }
2315 } else {
2316 self.skip_blank();
2317 }
2318 } else {
2319 if self.leading_whitespace {
2321 self.skip_break();
2322 self.buf_trailing_breaks.push('\n');
2323 } else {
2324 self.buf_whitespaces.clear();
2325 self.skip_break();
2326 self.buf_leading_break.push('\n');
2327 self.leading_whitespace = true;
2328 }
2329 }
2330 self.input.lookahead(2);
2331 }
2332
2333 if self.flow_level == 0 && (self.mark.col as isize) < indent {
2335 break;
2336 }
2337 }
2338
2339 if self.leading_whitespace {
2340 self.allow_simple_key();
2341 }
2342
2343 if string.is_empty() {
2344 Err(ScanError::new_str(
2348 start_mark,
2349 "unexpected end of plain scalar",
2350 ))
2351 } else {
2352 Ok(Token(
2353 Span::new(start_mark, end_mark),
2354 TokenType::Scalar(ScalarStyle::Plain, string.into()),
2355 ))
2356 }
2357 }
2358
2359 fn fetch_key(&mut self) -> ScanResult {
2360 let start_mark = self.mark;
2361 if self.flow_level == 0 {
2362 if !self.simple_key_allowed {
2364 return Err(ScanError::new_str(
2365 self.mark,
2366 "mapping keys are not allowed in this context",
2367 ));
2368 }
2369 self.roll_indent(
2370 start_mark.col,
2371 None,
2372 TokenType::BlockMappingStart,
2373 start_mark,
2374 );
2375 } else {
2376 self.flow_mapping_started = true;
2378 }
2379
2380 self.remove_simple_key()?;
2381
2382 if self.flow_level == 0 {
2383 self.allow_simple_key();
2384 } else {
2385 self.disallow_simple_key();
2386 }
2387
2388 self.skip_non_blank();
2389 self.skip_yaml_whitespace()?;
2390 if self.input.peek() == '\t' {
2391 return Err(ScanError::new_str(
2392 self.mark(),
2393 "tabs disallowed in this context",
2394 ));
2395 }
2396 self.tokens
2397 .push_back(Token(Span::new(start_mark, self.mark), TokenType::Key));
2398 Ok(())
2399 }
2400
2401 fn fetch_flow_value(&mut self) -> ScanResult {
2409 let nc = self.input.peek_nth(1);
2410
2411 if self.mark.index != self.adjacent_value_allowed_at && (nc == '[' || nc == '{') {
2423 return Err(ScanError::new_str(
2424 self.mark,
2425 "':' may not precede any of `[{` in flow mapping",
2426 ));
2427 }
2428
2429 self.fetch_value()
2430 }
2431
2432 fn fetch_value(&mut self) -> ScanResult {
2434 let sk = self.simple_keys.last().unwrap().clone();
2435 let start_mark = self.mark;
2436 let is_implicit_flow_mapping =
2437 !self.implicit_flow_mapping_states.is_empty() && !self.flow_mapping_started;
2438 if is_implicit_flow_mapping {
2439 *self.implicit_flow_mapping_states.last_mut().unwrap() = ImplicitMappingState::Inside;
2440 }
2441
2442 self.skip_non_blank();
2444 if self.input.look_ch() == '\t'
2445 && !self.skip_ws_to_eol(SkipTabs::Yes)?.has_valid_yaml_ws()
2446 && (self.input.peek() == '-' || self.input.next_is_alpha())
2447 {
2448 return Err(ScanError::new_str(
2449 self.mark,
2450 "':' must be followed by a valid YAML whitespace",
2451 ));
2452 }
2453
2454 if sk.possible {
2455 let tok = Token(Span::empty(sk.mark), TokenType::Key);
2457 self.insert_token(sk.token_number - self.tokens_parsed, tok);
2458 if is_implicit_flow_mapping {
2459 if sk.mark.line < start_mark.line {
2460 return Err(ScanError::new_str(
2461 start_mark,
2462 "illegal placement of ':' indicator",
2463 ));
2464 }
2465 self.insert_token(
2466 sk.token_number - self.tokens_parsed,
2467 Token(Span::empty(sk.mark), TokenType::FlowMappingStart),
2468 );
2469 }
2470
2471 self.roll_indent(
2473 sk.mark.col,
2474 Some(sk.token_number),
2475 TokenType::BlockMappingStart,
2476 sk.mark,
2477 );
2478 self.roll_one_col_indent();
2479
2480 self.simple_keys.last_mut().unwrap().possible = false;
2481 self.disallow_simple_key();
2482 } else {
2483 if is_implicit_flow_mapping {
2484 self.tokens
2485 .push_back(Token(Span::empty(start_mark), TokenType::FlowMappingStart));
2486 }
2487 if self.flow_level == 0 {
2489 if !self.simple_key_allowed {
2490 return Err(ScanError::new_str(
2491 start_mark,
2492 "mapping values are not allowed in this context",
2493 ));
2494 }
2495
2496 self.roll_indent(
2497 start_mark.col,
2498 None,
2499 TokenType::BlockMappingStart,
2500 start_mark,
2501 );
2502 }
2503 self.roll_one_col_indent();
2504
2505 if self.flow_level == 0 {
2506 self.allow_simple_key();
2507 } else {
2508 self.disallow_simple_key();
2509 }
2510 }
2511 self.tokens
2512 .push_back(Token(Span::empty(start_mark), TokenType::Value));
2513
2514 Ok(())
2515 }
2516
2517 fn roll_indent(
2523 &mut self,
2524 col: usize,
2525 number: Option<usize>,
2526 tok: TokenType<'input>,
2527 mark: Marker,
2528 ) {
2529 if self.flow_level > 0 {
2530 return;
2531 }
2532
2533 if self.indent <= col as isize {
2537 if let Some(indent) = self.indents.last() {
2538 if !indent.needs_block_end {
2539 self.indent = indent.indent;
2540 self.indents.pop();
2541 }
2542 }
2543 }
2544
2545 if self.indent < col as isize {
2546 self.indents.push(Indent {
2547 indent: self.indent,
2548 needs_block_end: true,
2549 });
2550 self.indent = col as isize;
2551 let tokens_parsed = self.tokens_parsed;
2552 match number {
2553 Some(n) => self.insert_token(n - tokens_parsed, Token(Span::empty(mark), tok)),
2554 None => self.tokens.push_back(Token(Span::empty(mark), tok)),
2555 }
2556 }
2557 }
2558
2559 fn unroll_indent(&mut self, col: isize) {
2565 if self.flow_level > 0 {
2566 return;
2567 }
2568 while self.indent > col {
2569 let indent = self.indents.pop().unwrap();
2570 self.indent = indent.indent;
2571 if indent.needs_block_end {
2572 self.tokens
2573 .push_back(Token(Span::empty(self.mark), TokenType::BlockEnd));
2574 }
2575 }
2576 }
2577
2578 fn roll_one_col_indent(&mut self) {
2584 if self.flow_level == 0 && self.indents.last().is_some_and(|x| x.needs_block_end) {
2585 self.indents.push(Indent {
2586 indent: self.indent,
2587 needs_block_end: false,
2588 });
2589 self.indent += 1;
2590 }
2591 }
2592
2593 fn unroll_non_block_indents(&mut self) {
2595 while let Some(indent) = self.indents.last() {
2596 if indent.needs_block_end {
2597 break;
2598 }
2599 self.indent = indent.indent;
2600 self.indents.pop();
2601 }
2602 }
2603
2604 fn save_simple_key(&mut self) {
2606 if self.simple_key_allowed {
2607 let required = self.flow_level == 0
2608 && self.indent == (self.mark.col as isize)
2609 && self.indents.last().unwrap().needs_block_end;
2610 let mut sk = SimpleKey::new(self.mark);
2611 sk.possible = true;
2612 sk.required = required;
2613 sk.token_number = self.tokens_parsed + self.tokens.len();
2614
2615 self.simple_keys.pop();
2616 self.simple_keys.push(sk);
2617 }
2618 }
2619
2620 fn remove_simple_key(&mut self) -> ScanResult {
2621 let last = self.simple_keys.last_mut().unwrap();
2622 if last.possible && last.required {
2623 return Err(ScanError::new_str(self.mark, "simple key expected"));
2624 }
2625
2626 last.possible = false;
2627 Ok(())
2628 }
2629
2630 fn is_within_block(&self) -> bool {
2632 !self.indents.is_empty()
2633 }
2634
2635 fn end_implicit_mapping(&mut self, mark: Marker) {
2641 if let Some(implicit_mapping) = self.implicit_flow_mapping_states.last_mut() {
2642 if *implicit_mapping == ImplicitMappingState::Inside {
2643 self.flow_mapping_started = false;
2644 *implicit_mapping = ImplicitMappingState::Possible;
2645 self.tokens
2646 .push_back(Token(Span::empty(mark), TokenType::FlowMappingEnd));
2647 }
2648 }
2649 }
2650}
2651
2652#[derive(PartialEq, Eq)]
2656pub enum Chomping {
2657 Strip,
2659 Clip,
2661 Keep,
2663}
2664
2665#[cfg(test)]
2666mod test {
2667 #[test]
2668 fn test_is_anchor_char() {
2669 use super::is_anchor_char;
2670 assert!(is_anchor_char('x'));
2671 }
2672}