1 use tests::memchr_tests;
2 use {Memchr, Memchr2, Memchr3};
3
4 #[test]
memchr1_iter()5 fn memchr1_iter() {
6 for test in memchr_tests() {
7 test.iter_one(false, Memchr::new);
8 }
9 }
10
11 #[test]
memchr2_iter()12 fn memchr2_iter() {
13 for test in memchr_tests() {
14 test.iter_two(false, Memchr2::new);
15 }
16 }
17
18 #[test]
memchr3_iter()19 fn memchr3_iter() {
20 for test in memchr_tests() {
21 test.iter_three(false, Memchr3::new);
22 }
23 }
24
25 #[test]
memrchr1_iter()26 fn memrchr1_iter() {
27 for test in memchr_tests() {
28 test.iter_one(true, |n1, corpus| Memchr::new(n1, corpus).rev());
29 }
30 }
31
32 #[test]
memrchr2_iter()33 fn memrchr2_iter() {
34 for test in memchr_tests() {
35 test.iter_two(true, |n1, n2, corpus| {
36 Memchr2::new(n1, n2, corpus).rev()
37 })
38 }
39 }
40
41 #[test]
memrchr3_iter()42 fn memrchr3_iter() {
43 for test in memchr_tests() {
44 test.iter_three(true, |n1, n2, n3, corpus| {
45 Memchr3::new(n1, n2, n3, corpus).rev()
46 })
47 }
48 }
49
50 quickcheck! {
51 fn qc_memchr_double_ended_iter(
52 needle: u8, data: Vec<u8>, take_side: Vec<bool>
53 ) -> bool {
54 // make nonempty
55 let mut take_side = take_side;
56 if take_side.is_empty() { take_side.push(true) };
57
58 let iter = Memchr::new(needle, &data);
59 let all_found = double_ended_take(
60 iter, take_side.iter().cycle().cloned());
61
62 all_found.iter().cloned().eq(positions1(needle, &data))
63 }
64
65 fn qc_memchr2_double_ended_iter(
66 needle1: u8, needle2: u8, data: Vec<u8>, take_side: Vec<bool>
67 ) -> bool {
68 // make nonempty
69 let mut take_side = take_side;
70 if take_side.is_empty() { take_side.push(true) };
71
72 let iter = Memchr2::new(needle1, needle2, &data);
73 let all_found = double_ended_take(
74 iter, take_side.iter().cycle().cloned());
75
76 all_found.iter().cloned().eq(positions2(needle1, needle2, &data))
77 }
78
79 fn qc_memchr3_double_ended_iter(
80 needle1: u8, needle2: u8, needle3: u8,
81 data: Vec<u8>, take_side: Vec<bool>
82 ) -> bool {
83 // make nonempty
84 let mut take_side = take_side;
85 if take_side.is_empty() { take_side.push(true) };
86
87 let iter = Memchr3::new(needle1, needle2, needle3, &data);
88 let all_found = double_ended_take(
89 iter, take_side.iter().cycle().cloned());
90
91 all_found
92 .iter()
93 .cloned()
94 .eq(positions3(needle1, needle2, needle3, &data))
95 }
96
97 fn qc_memchr1_iter(data: Vec<u8>) -> bool {
98 let needle = 0;
99 let answer = positions1(needle, &data);
100 answer.eq(Memchr::new(needle, &data))
101 }
102
103 fn qc_memchr1_rev_iter(data: Vec<u8>) -> bool {
104 let needle = 0;
105 let answer = positions1(needle, &data);
106 answer.rev().eq(Memchr::new(needle, &data).rev())
107 }
108
109 fn qc_memchr2_iter(data: Vec<u8>) -> bool {
110 let needle1 = 0;
111 let needle2 = 1;
112 let answer = positions2(needle1, needle2, &data);
113 answer.eq(Memchr2::new(needle1, needle2, &data))
114 }
115
116 fn qc_memchr2_rev_iter(data: Vec<u8>) -> bool {
117 let needle1 = 0;
118 let needle2 = 1;
119 let answer = positions2(needle1, needle2, &data);
120 answer.rev().eq(Memchr2::new(needle1, needle2, &data).rev())
121 }
122
123 fn qc_memchr3_iter(data: Vec<u8>) -> bool {
124 let needle1 = 0;
125 let needle2 = 1;
126 let needle3 = 2;
127 let answer = positions3(needle1, needle2, needle3, &data);
128 answer.eq(Memchr3::new(needle1, needle2, needle3, &data))
129 }
130
131 fn qc_memchr3_rev_iter(data: Vec<u8>) -> bool {
132 let needle1 = 0;
133 let needle2 = 1;
134 let needle3 = 2;
135 let answer = positions3(needle1, needle2, needle3, &data);
136 answer.rev().eq(Memchr3::new(needle1, needle2, needle3, &data).rev())
137 }
138
139 fn qc_memchr1_iter_size_hint(data: Vec<u8>) -> bool {
140 // test that the size hint is within reasonable bounds
141 let needle = 0;
142 let mut iter = Memchr::new(needle, &data);
143 let mut real_count = data
144 .iter()
145 .filter(|&&elt| elt == needle)
146 .count();
147
148 while let Some(index) = iter.next() {
149 real_count -= 1;
150 let (lower, upper) = iter.size_hint();
151 assert!(lower <= real_count);
152 assert!(upper.unwrap() >= real_count);
153 assert!(upper.unwrap() <= data.len() - index);
154 }
155 true
156 }
157 }
158
159 // take items from a DEI, taking front for each true and back for each false.
160 // Return a vector with the concatenation of the fronts and the reverse of the
161 // backs.
double_ended_take<I, J>(mut iter: I, take_side: J) -> Vec<I::Item> where I: DoubleEndedIterator, J: Iterator<Item = bool>,162 fn double_ended_take<I, J>(mut iter: I, take_side: J) -> Vec<I::Item>
163 where
164 I: DoubleEndedIterator,
165 J: Iterator<Item = bool>,
166 {
167 let mut found_front = Vec::new();
168 let mut found_back = Vec::new();
169
170 for take_front in take_side {
171 if take_front {
172 if let Some(pos) = iter.next() {
173 found_front.push(pos);
174 } else {
175 break;
176 }
177 } else {
178 if let Some(pos) = iter.next_back() {
179 found_back.push(pos);
180 } else {
181 break;
182 }
183 };
184 }
185
186 let mut all_found = found_front;
187 all_found.extend(found_back.into_iter().rev());
188 all_found
189 }
190
191 // return an iterator of the 0-based indices of haystack that match the needle
positions1<'a>( n1: u8, haystack: &'a [u8], ) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a>192 fn positions1<'a>(
193 n1: u8,
194 haystack: &'a [u8],
195 ) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a> {
196 let it = haystack
197 .iter()
198 .enumerate()
199 .filter(move |&(_, &b)| b == n1)
200 .map(|t| t.0);
201 Box::new(it)
202 }
203
positions2<'a>( n1: u8, n2: u8, haystack: &'a [u8], ) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a>204 fn positions2<'a>(
205 n1: u8,
206 n2: u8,
207 haystack: &'a [u8],
208 ) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a> {
209 let it = haystack
210 .iter()
211 .enumerate()
212 .filter(move |&(_, &b)| b == n1 || b == n2)
213 .map(|t| t.0);
214 Box::new(it)
215 }
216
positions3<'a>( n1: u8, n2: u8, n3: u8, haystack: &'a [u8], ) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a>217 fn positions3<'a>(
218 n1: u8,
219 n2: u8,
220 n3: u8,
221 haystack: &'a [u8],
222 ) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a> {
223 let it = haystack
224 .iter()
225 .enumerate()
226 .filter(move |&(_, &b)| b == n1 || b == n2 || b == n3)
227 .map(|t| t.0);
228 Box::new(it)
229 }
230