1 #[cfg(feature = "std")]
2 use proptest::prelude::*;
3 
4 use crate::error::ErrMode::Backtrack;
5 use crate::error::{ErrorKind, InputError};
6 use crate::token::tag;
7 use crate::{
8     combinator::{separated, separated_pair},
9     PResult, Parser,
10 };
11 
12 use super::*;
13 
14 #[cfg(feature = "std")]
15 #[test]
test_fxhashmap_compiles()16 fn test_fxhashmap_compiles() {
17     let input = "a=b";
18     fn pair(i: &mut &str) -> PResult<(char, char)> {
19         let out = separated_pair('a', '=', 'b').parse_next(i)?;
20         Ok(out)
21     }
22 
23     let _: rustc_hash::FxHashMap<char, char> = separated(0.., pair, ',').parse(input).unwrap();
24 }
25 
26 #[test]
test_offset_u8()27 fn test_offset_u8() {
28     let s = b"abcd123";
29     let a = &s[..];
30     let b = &a[2..];
31     let c = &a[..4];
32     let d = &a[3..5];
33     assert_eq!(b.offset_from(&a), 2);
34     assert_eq!(c.offset_from(&a), 0);
35     assert_eq!(d.offset_from(&a), 3);
36 }
37 
38 #[test]
test_offset_str()39 fn test_offset_str() {
40     let a = "abcřèÂßÇd123";
41     let b = &a[7..];
42     let c = &a[..5];
43     let d = &a[5..9];
44     assert_eq!(b.offset_from(&a), 7);
45     assert_eq!(c.offset_from(&a), 0);
46     assert_eq!(d.offset_from(&a), 5);
47 }
48 
49 #[test]
50 #[cfg(feature = "alloc")]
test_bit_stream_empty()51 fn test_bit_stream_empty() {
52     let i = (&b""[..], 0);
53 
54     let actual = i.iter_offsets().collect::<crate::lib::std::vec::Vec<_>>();
55     assert_eq!(actual, vec![]);
56 
57     let actual = i.eof_offset();
58     assert_eq!(actual, 0);
59 
60     let actual = i.peek_token();
61     assert_eq!(actual, None);
62 
63     let actual = i.offset_for(|b| b);
64     assert_eq!(actual, None);
65 
66     let actual = i.offset_at(1);
67     assert_eq!(actual, Err(Needed::new(1)));
68 
69     let (actual_input, actual_slice) = i.peek_slice(0);
70     assert_eq!(actual_input, (&b""[..], 0));
71     assert_eq!(actual_slice, (&b""[..], 0, 0));
72 }
73 
74 #[test]
75 #[cfg(feature = "alloc")]
test_bit_offset_empty()76 fn test_bit_offset_empty() {
77     let i = (&b""[..], 0);
78 
79     let actual = i.offset_from(&i);
80     assert_eq!(actual, 0);
81 }
82 
83 #[cfg(feature = "std")]
84 proptest! {
85   #[test]
86   #[cfg_attr(miri, ignore)]  // See https://github.com/AltSysrq/proptest/issues/253
87   fn bit_stream(byte_len in 0..20usize, start in 0..160usize) {
88         bit_stream_inner(byte_len, start);
89   }
90 }
91 
92 #[cfg(feature = "std")]
bit_stream_inner(byte_len: usize, start: usize)93 fn bit_stream_inner(byte_len: usize, start: usize) {
94     let start = start.min(byte_len * 8);
95     let start_byte = start / 8;
96     let start_bit = start % 8;
97 
98     let bytes = vec![0b1010_1010; byte_len];
99     let i = (&bytes[start_byte..], start_bit);
100 
101     let mut curr_i = i;
102     let mut curr_offset = 0;
103     while let Some((next_i, _token)) = curr_i.peek_token() {
104         let to_offset = curr_i.offset_from(&i);
105         assert_eq!(curr_offset, to_offset);
106 
107         let (slice_i, _) = i.peek_slice(curr_offset);
108         assert_eq!(curr_i, slice_i);
109 
110         let at_offset = i.offset_at(curr_offset).unwrap();
111         assert_eq!(curr_offset, at_offset);
112 
113         let eof_offset = curr_i.eof_offset();
114         let (next_eof_i, eof_slice) = curr_i.peek_slice(eof_offset);
115         assert_eq!(next_eof_i, (&b""[..], 0));
116         let eof_slice_i = (eof_slice.0, eof_slice.1);
117         assert_eq!(eof_slice_i, curr_i);
118 
119         curr_offset += 1;
120         curr_i = next_i;
121     }
122     assert_eq!(i.eof_offset(), curr_offset);
123 }
124 
125 #[test]
test_partial_complete()126 fn test_partial_complete() {
127     let mut i = Partial::new(&b""[..]);
128     assert!(Partial::<&[u8]>::is_partial_supported());
129 
130     assert!(i.is_partial(), "incomplete by default");
131     let incomplete_state = i.complete();
132     assert!(!i.is_partial(), "the stream should be marked as complete");
133 
134     i.restore_partial(incomplete_state);
135     assert!(i.is_partial(), "incomplete stream state should be restored");
136 }
137 
138 #[test]
test_custom_slice()139 fn test_custom_slice() {
140     type Token = usize;
141     type TokenSlice<'i> = &'i [Token];
142 
143     let mut tokens: TokenSlice<'_> = &[1, 2, 3, 4];
144 
145     let input = &mut tokens;
146     let start = input.checkpoint();
147     let _ = input.next_token();
148     let _ = input.next_token();
149     let offset = input.offset_from(&start);
150     assert_eq!(offset, 2);
151 }
152 
153 #[test]
test_tag_support_char()154 fn test_tag_support_char() {
155     assert_eq!(
156         tag::<_, _, InputError<_>>('π').parse_peek("π"),
157         Ok(("", "π"))
158     );
159     assert_eq!(
160         tag::<_, _, InputError<_>>('π').parse_peek("π3.14"),
161         Ok(("3.14", "π"))
162     );
163 
164     assert_eq!(
165         tag::<_, _, InputError<_>>("π").parse_peek("π3.14"),
166         Ok(("3.14", "π"))
167     );
168 
169     assert_eq!(
170         tag::<_, _, InputError<_>>('-').parse_peek("π"),
171         Err(Backtrack(InputError::new("π", ErrorKind::Tag)))
172     );
173 
174     assert_eq!(
175         tag::<_, Partial<&[u8]>, InputError<_>>('π').parse_peek(Partial::new(b"\xCF\x80")),
176         Ok((Partial::new(Default::default()), "π".as_bytes()))
177     );
178     assert_eq!(
179         tag::<_, &[u8], InputError<_>>('π').parse_peek(b"\xCF\x80"),
180         Ok((Default::default(), "π".as_bytes()))
181     );
182 
183     assert_eq!(
184         tag::<_, Partial<&[u8]>, InputError<_>>('π').parse_peek(Partial::new(b"\xCF\x803.14")),
185         Ok((Partial::new(&b"3.14"[..]), "π".as_bytes()))
186     );
187     assert_eq!(
188         tag::<_, &[u8], InputError<_>>('π').parse_peek(b"\xCF\x80"),
189         Ok((Default::default(), "π".as_bytes()))
190     );
191 
192     assert_eq!(
193         tag::<_, &[u8], InputError<_>>('π').parse_peek(b"\xCF\x803.14"),
194         Ok((&b"3.14"[..], "π".as_bytes()))
195     );
196 
197     assert_eq!(
198         tag::<_, &[u8], InputError<_>>(AsciiCaseless('a')).parse_peek(b"ABCxyz"),
199         Ok((&b"BCxyz"[..], &b"A"[..]))
200     );
201 
202     assert_eq!(
203         tag::<_, &[u8], InputError<_>>('a').parse_peek(b"ABCxyz"),
204         Err(Backtrack(InputError::new(&b"ABCxyz"[..], ErrorKind::Tag)))
205     );
206 
207     assert_eq!(
208         tag::<_, &[u8], InputError<_>>(AsciiCaseless('π')).parse_peek(b"\xCF\x803.14"),
209         Ok((&b"3.14"[..], "π".as_bytes()))
210     );
211 
212     assert_eq!(
213         tag::<_, _, InputError<_>>(AsciiCaseless('��')).parse_peek("��你好"),
214         Ok(("你好", "��"))
215     );
216 
217     let mut buffer = [0; 4];
218     let input = '\u{241b}'.encode_utf8(&mut buffer);
219     assert_eq!(
220         tag::<_, &[u8], InputError<_>>(AsciiCaseless('␛')).parse_peek(input.as_bytes()),
221         Ok((&b""[..], [226, 144, 155].as_slice()))
222     );
223 
224     assert_eq!(
225         tag::<_, &[u8], InputError<_>>('-').parse_peek(b"\xCF\x80"),
226         Err(Backtrack(InputError::new(&b"\xCF\x80"[..], ErrorKind::Tag)))
227     );
228 }
229