1 #![cfg(feature = "std")]
2
3 use combine::{
4 attempt, choice, many, many1,
5 parser::{
6 char::{char, digit, spaces, string},
7 combinator::recognize,
8 },
9 sep_by, skip_many1,
10 stream::{
11 buffered,
12 easy::{self, Error, Errors},
13 position, IteratorStream,
14 },
15 Parser, Positioned,
16 };
17
18 #[test]
shared_stream_buffer()19 fn shared_stream_buffer() {
20 // Iterator that can't be cloned
21 let text = "10,222,3,44".chars().map(|c| {
22 if c.is_digit(10) {
23 (c as u8 + 1) as char
24 } else {
25 c
26 }
27 });
28 let buffer = buffered::Stream::new(position::Stream::new(IteratorStream::new(text)), 1);
29 let int: &mut dyn Parser<_, Output = _, PartialState = _> =
30 &mut many(digit()).map(|s: String| s.parse::<i64>().unwrap());
31 let result = sep_by(int, char(',')).parse(buffer).map(|t| t.0);
32 assert_eq!(result, Ok(vec![21, 333, 4, 55]));
33 }
34
35 #[test]
shared_stream_backtrack()36 fn shared_stream_backtrack() {
37 let text = "apple,apple,ananas,orangeblah";
38 let mut iter = text.chars();
39 // Iterator that can't be cloned
40 let stream = buffered::Stream::new(position::Stream::new(IteratorStream::new(&mut iter)), 2);
41
42 let value: &mut dyn Parser<_, Output = _, PartialState = _> = &mut choice([
43 attempt(string("apple")),
44 attempt(string("orange")),
45 attempt(string("ananas")),
46 ]);
47 let mut parser = sep_by(value, char(','));
48 let result = parser.parse(stream).map(|t| t.0);
49 assert_eq!(result, Ok(vec!["apple", "apple", "ananas", "orange"]));
50 }
51
52 #[test]
shared_stream_insufficent_backtrack()53 fn shared_stream_insufficent_backtrack() {
54 let text = "apple,apple,ananas,orangeblah";
55 let mut iter = text.chars();
56 // Iterator that can't be cloned
57 let stream = buffered::Stream::new(
58 easy::Stream(position::Stream::new(IteratorStream::new(&mut iter))),
59 1,
60 );
61
62 let value: &mut dyn Parser<_, Output = _, PartialState = _> = &mut choice([
63 attempt(string("apple")),
64 attempt(string("orange")),
65 attempt(string("ananas")),
66 ]);
67 let mut parser = sep_by(value, char(','));
68 let result: Result<Vec<&str>, _> = parser.parse(stream).map(|t| t.0);
69 assert!(result.is_err());
70 assert!(
71 result
72 .as_ref()
73 .unwrap_err()
74 .errors
75 .iter()
76 .any(|err| *err == Error::Message("Backtracked to far".into())),
77 "{}",
78 result.unwrap_err()
79 );
80 }
81
82 /// Test which checks that a stream which has ended does not repeat the last token in some cases in
83 /// which case this test would loop forever
84 #[test]
always_output_end_of_input_after_end_of_input()85 fn always_output_end_of_input_after_end_of_input() {
86 let text = "10".chars();
87 let buffer = buffered::Stream::new(position::Stream::new(IteratorStream::new(text)), 1);
88 let int = many1(digit()).map(|s: String| s.parse::<i64>().unwrap());
89 let result = many(spaces().with(int)).parse(buffer).map(|t| t.0);
90 assert_eq!(result, Ok(vec![10]));
91 }
92
93 #[test]
position()94 fn position() {
95 let text = "10abc".chars();
96 let stream = buffered::Stream::new(position::Stream::new(IteratorStream::new(text)), 3);
97 assert_eq!(stream.position(), 0);
98 let result = many1::<Vec<_>, _, _>(digit()).parse(stream);
99 assert!(result.is_ok());
100 assert_eq!(result.unwrap().1.position(), 2);
101 }
102
103 #[test]
buffered_stream_recognize_issue_256()104 fn buffered_stream_recognize_issue_256() {
105 let mut parser = recognize::<String, _, _>(skip_many1(digit()));
106 let input = "12 ";
107 assert_eq!(
108 parser
109 .parse(buffered::Stream::new(easy::Stream(input), 1))
110 .map_err(|err| err.map_position(|pos| pos.translate_position(input))),
111 Err(Errors {
112 position: 2,
113 errors: vec![easy::Error::Message("Backtracked to far".into())]
114 })
115 );
116 }
117