1use std::num::NonZeroU8;
40
41use atoi::atoi;
42
43use crate::{
44 scanner::{
45 context::Context,
46 entry::MaybeToken,
47 error::{ScanError, ScanResult as Result},
48 flag::{Flags, O_LAZY},
49 scalar::as_maybe,
50 stats::MStats,
51 },
52 token::{ScalarStyle, Slice, Token},
53};
54
55pub(in crate::scanner) fn scan_block_scalar<'de>(
62 opts: Flags,
63 base: &'de str,
64 stats: &mut MStats,
65 cxt: &Context,
66 fold: bool,
67) -> Result<(MaybeToken<'de>, usize)>
68{
69 let indent = cxt.indent().as_usize();
73
74 match opts.contains(O_LAZY)
75 {
76 true => scan_block_scalar_lazy(opts, base, stats, indent, fold).map(as_maybe),
77 false => scan_block_scalar_eager(opts, base, stats, indent, fold).map(as_maybe),
78 }
79}
80pub(in crate::scanner) fn scan_block_scalar_eager<'de>(
89 opts: Flags,
90 base: &'de str,
91 stats: &mut MStats,
92 base_indent: usize,
93 fold: bool,
94) -> Result<(Token<'de>, usize)>
95{
96 let mut buffer = base;
98 let mut scratch = Vec::new();
99 let mut local_stats = stats.clone();
100
101 let mut can_borrow = true;
103
104 let mut content_start: usize = 0;
111 let mut content_end: usize = 0;
112
113 let mut lines: usize = 0;
116
117 let indent: usize;
119
120 let style = match fold
122 {
123 true => ScalarStyle::Folded,
124 false => ScalarStyle::Literal,
125 };
126
127 cache!(~buffer, 1, opts)?;
129 advance!(buffer, :local_stats, 1);
130
131 let (chomp, explicit) = scan_headers(opts, &mut buffer, &mut local_stats)?;
133
134 skip_blanks(opts, &mut buffer, &mut local_stats, COMMENTS)?;
137 cache!(~buffer, 1, opts)?;
138 if !isWhiteSpaceZ!(~buffer)
139 {
140 return Err(ScanError::InvalidBlockScalar);
141 }
142
143 advance!(buffer, :local_stats, @line);
145
146 match explicit.map(NonZeroU8::get)
149 {
150 Some(explicit) => indent = base_indent + explicit as usize,
151 None =>
152 {
153 indent = detect_indent_level(
154 opts,
155 &mut buffer,
156 &mut local_stats,
157 base_indent,
158 &mut lines,
159 &mut can_borrow,
160 )?
161 },
162 }
163
164 match can_borrow
167 {
168 true => content_start = local_stats.read - stats.read,
169 false =>
170 {
171 for _ in 0..lines
172 {
173 scratch.push(NEWLINE)
174 }
175 },
176 }
177
178 lines = 0;
179
180 while local_stats.column == indent && (!buffer.is_empty())
183 {
184 if can_borrow && lines > 0
196 {
197 scratch.extend_from_slice(base[content_start..content_end].as_bytes());
198
199 can_borrow = false
200 }
201
202 if fold
204 {
205 match lines
207 {
208 0 =>
210 {},
211 1 =>
214 {
215 scratch.push(SPACE);
216 },
217 n =>
219 {
220 for _ in 0..n - 1
222 {
223 scratch.push(NEWLINE)
224 }
225 },
226 }
227 }
228 else
230 {
231 for _ in 0..lines
232 {
233 scratch.push(NEWLINE)
234 }
235 }
236
237 lines = 0;
239
240 match can_borrow
242 {
243 true =>
244 {
245 if content_start == 0
246 {
247 content_start = local_stats.read - stats.read
248 }
249 },
250 false => content_start = 0,
251 }
252
253 cache!(~buffer, 1, opts)?;
255 while !isBreakZ!(~buffer)
256 {
257 cache!(~buffer, 1, opts)?;
258
259 if !can_borrow
260 {
261 scratch.push(buffer.as_bytes()[0])
262 }
263 advance!(buffer, :local_stats, 1);
264 }
265
266 match can_borrow
268 {
269 true => content_end = local_stats.read - stats.read,
270 false => content_end = scratch.len(),
271 }
272
273 cache!(~buffer, 1, opts)?;
275 if isBreak!(~buffer)
276 {
277 advance!(buffer, :local_stats, @line);
278 lines += 1;
279 }
280
281 scan_indent(
283 opts,
284 &mut buffer,
285 &mut local_stats,
286 &mut lines,
287 &mut can_borrow,
288 indent,
289 )?;
290 }
291
292 let c_params = ChompParams::new(chomp, content_start, content_end, lines);
294 let scalar = scan_chomp(base, scratch, &mut can_borrow, c_params)?;
295
296 *stats = local_stats;
297 let advance = base.len() - buffer.len();
298 let token = Token::Scalar(scalar, style);
299
300 Ok((token, advance))
301}
302
303pub(in crate::scanner) fn scan_block_scalar_lazy<'de>(
304 opts: Flags,
305 base: &'de str,
306 stats: &mut MStats,
307 base_indent: usize,
308 fold: bool,
309) -> Result<(Deferred<'de>, usize)>
310{
311 let mut buffer = base;
313 let mut local_stats = stats.clone();
314
315 let indent: usize;
317
318 cache!(~buffer, 1, opts)?;
320 advance!(buffer, :local_stats, 1);
321
322 let (_, explicit) = scan_headers(opts, &mut buffer, &mut local_stats)?;
324
325 skip_blanks(opts, &mut buffer, &mut local_stats, COMMENTS)?;
328 cache!(~buffer, 1, opts)?;
329 if !isWhiteSpaceZ!(~buffer)
330 {
331 return Err(ScanError::InvalidBlockScalar);
332 }
333
334 advance!(buffer, :local_stats, @line);
336
337 match explicit.map(NonZeroU8::get)
340 {
341 Some(explicit) => indent = base_indent + explicit as usize,
342 None =>
343 {
344 indent = detect_indent_level(
345 opts,
346 &mut buffer,
347 &mut local_stats,
348 base_indent,
349 &mut 0,
350 &mut false,
351 )?
352 },
353 }
354
355 while local_stats.column == indent && (!buffer.is_empty())
356 {
357 cache!(~buffer, 1, opts)?;
363 while !isBreakZ!(~buffer)
364 {
365 cache!(~buffer, 1, opts)?;
366 advance!(buffer, :local_stats, 1);
367 }
368
369 cache!(~buffer, 1, opts)?;
371 if isBreak!(~buffer)
372 {
373 advance!(buffer, :local_stats, @line);
374 }
375
376 scan_indent(
378 opts,
379 &mut buffer,
380 &mut local_stats,
381 &mut 0,
382 &mut false,
383 indent,
384 )?;
385 }
386
387 let advance = base.len() - buffer.len();
388 let slice = &base[..advance];
389
390 let lazy = Deferred::new(opts, slice, stats.clone(), base_indent, fold);
391
392 *stats = local_stats;
393
394 Ok((lazy, advance))
395}
396
397fn scan_headers(
399 opts: Flags,
400 buffer: &mut &str,
401 stats: &mut MStats,
402) -> Result<(ChompStyle, IndentHeader)>
403{
404 let mut skip = 0;
405 let mut indent = None;
406 let mut chomp = ChompStyle::Clip;
407
408 cache!(~buffer, 2, opts)?;
409
410 match buffer.as_bytes()
415 {
416 [i @ b'0'..=b'9', ..] | [_, i @ b'0'..=b'9', ..] =>
417 {
418 indent = atoi::<u8>(&[*i]).and_then(NonZeroU8::new);
419 skip += 1;
420 },
421 _ =>
422 {},
423 }
424
425 match buffer.as_bytes()
427 {
428 [c, ..] | [_, c, ..] if matches!(*c, b'+') =>
429 {
430 chomp = ChompStyle::Keep;
431 skip += 1;
432 },
433 [c, ..] | [_, c, ..] if matches!(*c, b'-') =>
434 {
435 chomp = ChompStyle::Strip;
436 skip += 1;
437 },
438 _ =>
439 {},
440 }
441
442 advance!(*buffer, :stats, skip);
443
444 Ok((chomp, indent))
445}
446
447fn scan_indent(
449 opts: Flags,
450 buffer: &mut &str,
451 stats: &mut MStats,
452 lines: &mut usize,
453 _can_borrow: &mut bool,
454 indent: usize,
455) -> Result<bool>
456{
457 if stats.column >= indent
458 {
459 return Ok(false);
460 }
461
462 cache!(~buffer, 1, opts)?;
463
464 while stats.column < indent && isWhiteSpace!(~buffer)
465 {
466 if check!(~buffer => b' ')
468 {
469 advance!(*buffer, :stats, 1);
470 }
471 else if check!(~buffer => b'\t')
473 {
474 return Err(ScanError::InvalidTab);
475 }
476 else if isBreak!(~buffer)
478 {
479 *lines += 1;
480 advance!(*buffer, :stats, @line);
481 }
482
483 cache!(~buffer, 1, opts)?;
484 }
485
486 Ok(true)
487}
488
489fn scan_chomp<'de>(
495 base: &'de str,
496 mut scratch: Vec<u8>,
497 can_borrow: &mut bool,
498 params: ChompParams,
499) -> Result<Slice<'de>>
500{
501 let mut scalar = cow!("");
502 let ChompParams {
503 style,
504 start,
505 mut end,
506 mut lines,
507 } = params;
508
509 if *can_borrow
510 {
511 match style
512 {
513 ChompStyle::Clip =>
515 {
516 if lines > 0
519 {
520 end += widthOf!(~base[end..], 1);
521 }
522
523 scalar = cow!(&base[start..end])
524 },
525 ChompStyle::Strip => scalar = cow!(&base[start..end]),
527 ChompStyle::Keep => match lines
532 {
533 n @ 0 | n @ 1 => scalar = cow!(&base[start..end + n]),
534 _ =>
542 {
543 scratch.extend_from_slice(base[start..end].as_bytes());
544
545 while lines > 0
546 {
547 scratch.push(NEWLINE);
548 lines -= 1;
549 }
550
551 *can_borrow = false;
554 },
555 },
556 }
557 }
558
559 if !*can_borrow
560 {
561 match style
562 {
563 ChompStyle::Clip =>
565 {
566 if lines > 0
567 {
568 scratch.push(NEWLINE);
569 end += 1;
570 }
571
572 scratch.truncate(end);
573 },
574 ChompStyle::Strip => scratch.truncate(end),
576 ChompStyle::Keep =>
579 {
580 for _ in 0..lines
581 {
582 scratch.push(NEWLINE)
583 }
584 },
585 }
586
587 scalar = cow!(String::from_utf8(scratch).unwrap());
588 }
589
590 Ok(scalar)
591}
592
593fn detect_indent_level(
596 opts: Flags,
597 buffer: &mut &str,
598 stats: &mut MStats,
599 base_indent: usize,
600 lines: &mut usize,
601 can_borrow: &mut bool,
602) -> Result<usize>
603{
604 let mut indent = 0;
605
606 loop
607 {
608 cache!(~buffer, 1, opts)?;
609
610 while isBlank!(~buffer)
612 {
613 cache!(~buffer, 1, opts)?;
614
615 if check!(~buffer => b'\t')
616 {
617 return Err(ScanError::InvalidTab);
618 }
619
620 if *can_borrow && *lines > 0
621 {
622 *can_borrow = false
623 }
624
625 advance!(*buffer, :stats, 1);
626 }
627
628 if stats.column > indent
630 {
631 indent = stats.column;
632 }
633
634 cache!(~buffer, 1, opts)?;
636 if !isBreak!(~buffer)
637 {
638 break;
639 }
640
641 advance!(*buffer, :stats, @line);
643 *lines += 1;
644 }
645
646 if indent < base_indent + 1
649 {
650 indent = base_indent + 1
651 }
652
653 Ok(indent)
654}
655
656fn skip_blanks(opts: Flags, buffer: &mut &str, stats: &mut MStats, comments: bool) -> Result<()>
659{
660 cache!(~buffer, 1, opts)?;
661
662 while isBlank!(~buffer)
663 {
664 cache!(~buffer, 1, opts)?;
665 advance!(*buffer, :stats, 1);
666 }
667
668 if comments && check!(~buffer => b'#')
669 {
670 while !isBreakZ!(~buffer)
671 {
672 cache!(~buffer, 1, opts)?;
673 advance!(*buffer, :stats, 1);
674 }
675 }
676
677 Ok(())
678}
679
680#[derive(Debug, Clone, Copy, PartialEq, Eq)]
682enum ChompStyle
683{
684 Clip,
690 Strip,
695 Keep,
701}
702
703impl Default for ChompStyle
704{
705 fn default() -> Self
706 {
707 Self::Clip
708 }
709}
710
711#[derive(Debug)]
714struct ChompParams
715{
716 pub style: ChompStyle,
717 pub start: usize,
718 pub end: usize,
719 pub lines: usize,
720}
721
722impl ChompParams
723{
724 fn new(style: ChompStyle, start: usize, end: usize, lines: usize) -> Self
725 {
726 Self {
727 style,
728 start,
729 end,
730 lines,
731 }
732 }
733}
734
735#[derive(Debug, Clone)]
736pub(in crate::scanner) struct Deferred<'de>
737{
738 opts: Flags,
739 slice: &'de str,
740 stats: MStats,
741 indent: usize,
742 fold: bool,
743}
744
745impl<'de> Deferred<'de>
746{
747 pub fn new(opts: Flags, slice: &'de str, stats: MStats, indent: usize, fold: bool) -> Self
748 {
749 Self {
750 opts,
751 slice,
752 stats,
753 indent,
754 fold,
755 }
756 }
757
758 pub fn into_token(self) -> Result<Token<'de>>
759 {
760 let Deferred {
761 opts,
762 slice,
763 mut stats,
764 indent,
765 fold,
766 } = self;
767
768 scan_block_scalar_eager(opts, slice, &mut stats, indent, fold).map(|(t, _)| t)
769 }
770}
771
772type IndentHeader = Option<NonZeroU8>;
775
776const COMMENTS: bool = true;
777const SPACE: u8 = b' ';
778const NEWLINE: u8 = b'\n';
779
780#[cfg(test)]
781mod tests
782{
783 use pretty_assertions::assert_eq;
784 use ScalarStyle::{Folded, Literal};
785
786 use super::*;
787 use crate::scanner::scalar::test_utils::{normalize, TestResult, TEST_FLAGS};
788
789 macro_rules! cxt {
790 (flow -> $level:expr) => {
791 {
792 let mut c = Context::new();
793
794 for _ in 0..$level {
795 c.flow_increment().unwrap();
796 }
797
798 c
799 }
800 };
801 (block -> [ $($indent:expr),+ ]) => {
802 {
803 let mut c = Context::new();
804 $( cxt!(@blk &mut c, $indent) )+;
805
806 c
807 }
808 };
809 (@blk $cxt:expr, $indent:expr) => {
810 $cxt.indent_increment($indent, 0, true).unwrap()
811 }
812 }
813
814 #[test]
817 fn literal_simple() -> TestResult
818 {
819 let data = "|\n this is a simple block scalar";
820 let mut stats = MStats::new();
821 let cxt = cxt!(block -> [0]);
822 let expected = Token::Scalar(cow!("this is a simple block scalar"), Literal);
823
824 let (token, _amt) =
825 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, LITERAL).and_then(normalize)?;
826
827 assert_eq!(token, expected);
828
829 Ok(())
830 }
831
832 #[test]
833 fn literal_clip() -> TestResult
834 {
835 let data = "|\n trailing lines...\n \n\n";
836 let mut stats = MStats::new();
837 let cxt = cxt!(block -> [0]);
838 let expected = Token::Scalar(cow!("trailing lines...\n"), Literal);
839
840 let (token, _amt) =
841 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, LITERAL).and_then(normalize)?;
842
843 assert_eq!(token, expected);
844
845 Ok(())
846 }
847
848 #[test]
849 fn literal_strip() -> TestResult
850 {
851 let data = "|-\n trailing lines...\n \n\n";
852 let mut stats = MStats::new();
853 let cxt = cxt!(block -> [0]);
854 let expected = Token::Scalar(cow!("trailing lines..."), Literal);
855
856 let (token, _amt) =
857 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, LITERAL).and_then(normalize)?;
858
859 assert_eq!(token, expected);
860
861 Ok(())
862 }
863
864 #[test]
865 fn literal_keep() -> TestResult
866 {
867 let data = "|+\n trailing lines...\n \n\n";
868 let mut stats = MStats::new();
869 let cxt = cxt!(block -> [0]);
870 let expected = Token::Scalar(cow!("trailing lines...\n\n\n"), Literal);
871
872 let (token, _amt) =
873 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, LITERAL).and_then(normalize)?;
874
875 assert_eq!(token, expected);
876
877 Ok(())
878 }
879
880 #[test]
881 fn literal_line_folding() -> TestResult
882 {
883 let data = "|
884 some folded
885 lines
886 here
887";
888 let mut stats = MStats::new();
889 let cxt = cxt!(block -> [0]);
890 let expected = Token::Scalar(cow!("some folded\nlines\nhere\n"), Literal);
891
892 let (token, _amt) =
893 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, LITERAL).and_then(normalize)?;
894
895 assert_eq!(token, expected);
896
897 Ok(())
898 }
899
900 #[test]
901 fn literal_preceding_breaks() -> TestResult
902 {
903 let data = "|-
904
905
906 some folded
907 lines
908 here
909";
910 let mut stats = MStats::new();
911 let cxt = cxt!(block -> [0]);
912 let expected = Token::Scalar(cow!("\n\nsome folded\nlines\nhere"), Literal);
913
914 let (token, _amt) =
915 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, LITERAL).and_then(normalize)?;
916
917 assert_eq!(token, expected);
918
919 Ok(())
920 }
921
922 #[test]
923 fn literal_trailing_breaks() -> TestResult
924 {
925 let data = "|+
926 some folded
927 lines
928 here
929
930
931";
932 let mut stats = MStats::new();
933 let cxt = cxt!(block -> [0]);
934 let expected = Token::Scalar(cow!("some folded\nlines\nhere\n\n\n"), Literal);
935
936 let (token, _amt) =
937 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, LITERAL).and_then(normalize)?;
938
939 assert_eq!(token, expected);
940
941 Ok(())
942 }
943
944 #[test]
945 fn literal_trailing_chars() -> TestResult
946 {
947 let data = "|+
948 some folded
949 lines
950 here
951
952
953some.other.key: value";
954 let mut stats = MStats::new();
955 let cxt = cxt!(block -> [0]);
956 let expected = Token::Scalar(cow!("some folded\nlines\nhere\n\n\n"), Literal);
957
958 let (token, _amt) =
959 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, LITERAL).and_then(normalize)?;
960
961 assert_eq!(token, expected);
962
963 Ok(())
964 }
965
966 #[test]
967 fn literal_interior_breaks() -> TestResult
968 {
969 let data = "|-
970 this
971
972 has
973
974 breaks
975";
976 let mut stats = MStats::new();
977 let cxt = cxt!(block -> [0]);
978 let expected = Token::Scalar(cow!("this\n\nhas\n\nbreaks"), Literal);
979
980 let (token, _amt) =
981 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, LITERAL).and_then(normalize)?;
982
983 assert_eq!(token, expected);
984
985 Ok(())
986 }
987
988 #[test]
989 fn literal_comment() -> TestResult
990 {
991 let data = "| # a comment here.\n simple block scalar";
992 let mut stats = MStats::new();
993 let cxt = cxt!(block -> [0]);
994 let expected = Token::Scalar(cow!("simple block scalar"), Literal);
995
996 let (token, _amt) =
997 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, LITERAL).and_then(normalize)?;
998
999 assert_eq!(token, expected);
1000
1001 Ok(())
1002 }
1003
1004 #[test]
1007 fn folded_simple() -> TestResult
1008 {
1009 let data = ">\n this is a simple block scalar";
1010 let mut stats = MStats::new();
1011 let cxt = cxt!(block -> [0]);
1012 let expected = Token::Scalar(cow!("this is a simple block scalar"), Folded);
1013
1014 let (token, _amt) =
1015 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, !LITERAL).and_then(normalize)?;
1016
1017 assert_eq!(token, expected);
1018
1019 Ok(())
1020 }
1021
1022 #[test]
1023 fn folded_clip() -> TestResult
1024 {
1025 let data = ">\n trailing lines...\n \n\n";
1026 let mut stats = MStats::new();
1027 let cxt = cxt!(block -> [0]);
1028 let expected = Token::Scalar(cow!("trailing lines...\n"), Folded);
1029
1030 let (token, _amt) =
1031 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, !LITERAL).and_then(normalize)?;
1032
1033 assert_eq!(token, expected);
1034
1035 Ok(())
1036 }
1037
1038 #[test]
1039 fn folded_strip() -> TestResult
1040 {
1041 let data = ">-\n trailing lines...\n \n\n";
1042 let mut stats = MStats::new();
1043 let cxt = cxt!(block -> [0]);
1044 let expected = Token::Scalar(cow!("trailing lines..."), Folded);
1045
1046 let (token, _amt) =
1047 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, !LITERAL).and_then(normalize)?;
1048
1049 assert_eq!(token, expected);
1050
1051 Ok(())
1052 }
1053
1054 #[test]
1055 fn folded_keep() -> TestResult
1056 {
1057 let data = ">+\n trailing lines...\n \n\n";
1058 let mut stats = MStats::new();
1059 let cxt = cxt!(block -> [0]);
1060 let expected = Token::Scalar(cow!("trailing lines...\n\n\n"), Folded);
1061
1062 let (token, _amt) =
1063 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, !LITERAL).and_then(normalize)?;
1064
1065 assert_eq!(token, expected);
1066
1067 Ok(())
1068 }
1069
1070 #[test]
1071 fn folded_line_folding() -> TestResult
1072 {
1073 let data = ">
1074 some folded
1075 lines
1076 here
1077";
1078 let mut stats = MStats::new();
1079 let cxt = cxt!(block -> [0]);
1080 let expected = Token::Scalar(cow!("some folded lines here\n"), Folded);
1081
1082 let (token, _amt) =
1083 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, !LITERAL).and_then(normalize)?;
1084
1085 assert_eq!(token, expected);
1086
1087 Ok(())
1088 }
1089
1090 #[test]
1091 fn folded_preceding_breaks() -> TestResult
1092 {
1093 let data = ">-
1094
1095
1096 some folded
1097 lines
1098 here
1099";
1100 let mut stats = MStats::new();
1101 let cxt = cxt!(block -> [0]);
1102 let expected = Token::Scalar(cow!("\n\nsome folded lines here"), Folded);
1103
1104 let (token, _amt) =
1105 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, !LITERAL).and_then(normalize)?;
1106
1107 assert_eq!(token, expected);
1108
1109 Ok(())
1110 }
1111
1112 #[test]
1113 fn folded_trailing_breaks() -> TestResult
1114 {
1115 let data = ">+
1116 some folded
1117 lines
1118 here
1119
1120
1121";
1122 let mut stats = MStats::new();
1123 let cxt = cxt!(block -> [0]);
1124 let expected = Token::Scalar(cow!("some folded lines here\n\n\n"), Folded);
1125
1126 let (token, _amt) =
1127 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, !LITERAL).and_then(normalize)?;
1128
1129 assert_eq!(token, expected);
1130
1131 Ok(())
1132 }
1133
1134 #[test]
1135 fn folded_trailing_chars() -> TestResult
1136 {
1137 let data = ">+
1138 some folded
1139 lines
1140 here
1141
1142
1143some.other.key: value";
1144 let mut stats = MStats::new();
1145 let cxt = cxt!(block -> [0]);
1146 let expected = Token::Scalar(cow!("some folded lines here\n\n\n"), Folded);
1147
1148 let (token, _amt) =
1149 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, !LITERAL).and_then(normalize)?;
1150
1151 assert_eq!(token, expected);
1152
1153 Ok(())
1154 }
1155
1156 #[test]
1157 fn folded_interior_breaks() -> TestResult
1158 {
1159 let data = ">-
1160 this
1161
1162 has
1163
1164 breaks
1165";
1166 let mut stats = MStats::new();
1167 let cxt = cxt!(block -> [0]);
1168 let expected = Token::Scalar(cow!("this\nhas\nbreaks"), Folded);
1169
1170 let (token, _amt) =
1171 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, !LITERAL).and_then(normalize)?;
1172
1173 assert_eq!(token, expected);
1174
1175 Ok(())
1176 }
1177
1178 #[test]
1179 fn folded_comment() -> TestResult
1180 {
1181 let data = "> # a comment here.\n simple block scalar";
1182 let mut stats = MStats::new();
1183 let cxt = cxt!(block -> [0]);
1184 let expected = Token::Scalar(cow!("simple block scalar"), Folded);
1185
1186 let (token, _amt) =
1187 scan_block_scalar(TEST_FLAGS, data, &mut stats, &cxt, !LITERAL).and_then(normalize)?;
1188
1189 assert_eq!(token, expected);
1190
1191 Ok(())
1192 }
1193
1194 const LITERAL: bool = false;
1195}