/rust/registry/src/index.crates.io-1949cf8c6b5b557f/arbitrary-1.3.2/src/unstructured.rs
Line | Count | Source |
1 | | // Copyright © 2019 The Rust Fuzz Project Developers. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
4 | | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
5 | | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
6 | | // option. This file may not be copied, modified, or distributed |
7 | | // except according to those terms. |
8 | | |
9 | | //! Wrappers around raw, unstructured bytes. |
10 | | |
11 | | use crate::{Arbitrary, Error, Result}; |
12 | | use std::marker::PhantomData; |
13 | | use std::ops::ControlFlow; |
14 | | use std::{mem, ops}; |
15 | | |
16 | | /// A source of unstructured data. |
17 | | /// |
18 | | /// An `Unstructured` helps `Arbitrary` implementations interpret raw data |
19 | | /// (typically provided by a fuzzer) as a "DNA string" that describes how to |
20 | | /// construct the `Arbitrary` type. The goal is that a small change to the "DNA |
21 | | /// string" (the raw data wrapped by an `Unstructured`) results in a small |
22 | | /// change to the generated `Arbitrary` instance. This helps a fuzzer |
23 | | /// efficiently explore the `Arbitrary`'s input space. |
24 | | /// |
25 | | /// `Unstructured` is deterministic: given the same raw data, the same series of |
26 | | /// API calls will return the same results (modulo system resource constraints, |
27 | | /// like running out of memory). However, `Unstructured` does not guarantee |
28 | | /// anything beyond that: it makes not guarantee that it will yield bytes from |
29 | | /// the underlying data in any particular order. |
30 | | /// |
31 | | /// You shouldn't generally need to use an `Unstructured` unless you are writing |
32 | | /// a custom `Arbitrary` implementation by hand, instead of deriving it. Mostly, |
33 | | /// you should just be passing it through to nested `Arbitrary::arbitrary` |
34 | | /// calls. |
35 | | /// |
36 | | /// # Example |
37 | | /// |
38 | | /// Imagine you were writing a color conversion crate. You might want to write |
39 | | /// fuzz tests that take a random RGB color and assert various properties, run |
40 | | /// functions and make sure nothing panics, etc. |
41 | | /// |
42 | | /// Below is what translating the fuzzer's raw input into an `Unstructured` and |
43 | | /// using that to generate an arbitrary RGB color might look like: |
44 | | /// |
45 | | /// ``` |
46 | | /// # #[cfg(feature = "derive")] fn foo() { |
47 | | /// use arbitrary::{Arbitrary, Unstructured}; |
48 | | /// |
49 | | /// /// An RGB color. |
50 | | /// #[derive(Arbitrary)] |
51 | | /// pub struct Rgb { |
52 | | /// r: u8, |
53 | | /// g: u8, |
54 | | /// b: u8, |
55 | | /// } |
56 | | /// |
57 | | /// // Get the raw bytes from the fuzzer. |
58 | | /// # let get_input_from_fuzzer = || &[]; |
59 | | /// let raw_data: &[u8] = get_input_from_fuzzer(); |
60 | | /// |
61 | | /// // Wrap it in an `Unstructured`. |
62 | | /// let mut unstructured = Unstructured::new(raw_data); |
63 | | /// |
64 | | /// // Generate an `Rgb` color and run our checks. |
65 | | /// if let Ok(rgb) = Rgb::arbitrary(&mut unstructured) { |
66 | | /// # let run_my_color_conversion_checks = |_| {}; |
67 | | /// run_my_color_conversion_checks(rgb); |
68 | | /// } |
69 | | /// # } |
70 | | /// ``` |
71 | | pub struct Unstructured<'a> { |
72 | | data: &'a [u8], |
73 | | } |
74 | | |
75 | | impl<'a> Unstructured<'a> { |
76 | | /// Create a new `Unstructured` from the given raw data. |
77 | | /// |
78 | | /// # Example |
79 | | /// |
80 | | /// ``` |
81 | | /// use arbitrary::Unstructured; |
82 | | /// |
83 | | /// let u = Unstructured::new(&[1, 2, 3, 4]); |
84 | | /// ``` |
85 | 18.9k | pub fn new(data: &'a [u8]) -> Self { |
86 | 18.9k | Unstructured { data } |
87 | 18.9k | } |
88 | | |
89 | | /// Get the number of remaining bytes of underlying data that are still |
90 | | /// available. |
91 | | /// |
92 | | /// # Example |
93 | | /// |
94 | | /// ``` |
95 | | /// use arbitrary::{Arbitrary, Unstructured}; |
96 | | /// |
97 | | /// let mut u = Unstructured::new(&[1, 2, 3]); |
98 | | /// |
99 | | /// // Initially have three bytes of data. |
100 | | /// assert_eq!(u.len(), 3); |
101 | | /// |
102 | | /// // Generating a `bool` consumes one byte from the underlying data, so |
103 | | /// // we are left with two bytes afterwards. |
104 | | /// let _ = bool::arbitrary(&mut u); |
105 | | /// assert_eq!(u.len(), 2); |
106 | | /// ``` |
107 | | #[inline] |
108 | 5.35M | pub fn len(&self) -> usize { |
109 | 5.35M | self.data.len() |
110 | 5.35M | } <arbitrary::unstructured::Unstructured>::len Line | Count | Source | 108 | 1.84k | pub fn len(&self) -> usize { | 109 | 1.84k | self.data.len() | 110 | 1.84k | } |
<arbitrary::unstructured::Unstructured>::len Line | Count | Source | 108 | 2.28M | pub fn len(&self) -> usize { | 109 | 2.28M | self.data.len() | 110 | 2.28M | } |
<arbitrary::unstructured::Unstructured>::len Line | Count | Source | 108 | 2.09M | pub fn len(&self) -> usize { | 109 | 2.09M | self.data.len() | 110 | 2.09M | } |
<arbitrary::unstructured::Unstructured>::len Line | Count | Source | 108 | 967k | pub fn len(&self) -> usize { | 109 | 967k | self.data.len() | 110 | 967k | } |
|
111 | | |
112 | | /// Is the underlying unstructured data exhausted? |
113 | | /// |
114 | | /// `unstructured.is_empty()` is the same as `unstructured.len() == 0`. |
115 | | /// |
116 | | /// # Example |
117 | | /// |
118 | | /// ``` |
119 | | /// use arbitrary::{Arbitrary, Unstructured}; |
120 | | /// |
121 | | /// let mut u = Unstructured::new(&[1, 2, 3, 4]); |
122 | | /// |
123 | | /// // Initially, we are not empty. |
124 | | /// assert!(!u.is_empty()); |
125 | | /// |
126 | | /// // Generating a `u32` consumes all four bytes of the underlying data, so |
127 | | /// // we become empty afterwards. |
128 | | /// let _ = u32::arbitrary(&mut u); |
129 | | /// assert!(u.is_empty()); |
130 | | /// ``` |
131 | | #[inline] |
132 | 5.34M | pub fn is_empty(&self) -> bool { |
133 | 5.34M | self.len() == 0 |
134 | 5.34M | } Unexecuted instantiation: <arbitrary::unstructured::Unstructured>::is_empty <arbitrary::unstructured::Unstructured>::is_empty Line | Count | Source | 132 | 2.28M | pub fn is_empty(&self) -> bool { | 133 | 2.28M | self.len() == 0 | 134 | 2.28M | } |
<arbitrary::unstructured::Unstructured>::is_empty Line | Count | Source | 132 | 2.09M | pub fn is_empty(&self) -> bool { | 133 | 2.09M | self.len() == 0 | 134 | 2.09M | } |
<arbitrary::unstructured::Unstructured>::is_empty Line | Count | Source | 132 | 967k | pub fn is_empty(&self) -> bool { | 133 | 967k | self.len() == 0 | 134 | 967k | } |
|
135 | | |
136 | | /// Generate an arbitrary instance of `A`. |
137 | | /// |
138 | | /// This is simply a helper method that is equivalent to `<A as |
139 | | /// Arbitrary>::arbitrary(self)`. This helper is a little bit more concise, |
140 | | /// and can be used in situations where Rust's type inference will figure |
141 | | /// out what `A` should be. |
142 | | /// |
143 | | /// # Example |
144 | | /// |
145 | | /// ``` |
146 | | /// # #[cfg(feature="derive")] fn foo() -> arbitrary::Result<()> { |
147 | | /// use arbitrary::{Arbitrary, Unstructured}; |
148 | | /// |
149 | | /// #[derive(Arbitrary)] |
150 | | /// struct MyType { |
151 | | /// // ... |
152 | | /// } |
153 | | /// |
154 | | /// fn do_stuff(value: MyType) { |
155 | | /// # let _ = value; |
156 | | /// // ... |
157 | | /// } |
158 | | /// |
159 | | /// let mut u = Unstructured::new(&[1, 2, 3, 4]); |
160 | | /// |
161 | | /// // Rust's type inference can figure out that `value` should be of type |
162 | | /// // `MyType` here: |
163 | | /// let value = u.arbitrary()?; |
164 | | /// do_stuff(value); |
165 | | /// # Ok(()) } |
166 | | /// ``` |
167 | 5.35M | pub fn arbitrary<A>(&mut self) -> Result<A> |
168 | 5.35M | where |
169 | 5.35M | A: Arbitrary<'a>, |
170 | | { |
171 | 5.35M | <A as Arbitrary<'a>>::arbitrary(self) |
172 | 5.35M | } Unexecuted instantiation: <arbitrary::unstructured::Unstructured>::arbitrary::<core::net::ip_addr::Ipv4Addr> Unexecuted instantiation: <arbitrary::unstructured::Unstructured>::arbitrary::<core::net::ip_addr::Ipv6Addr> <arbitrary::unstructured::Unstructured>::arbitrary::<bool> Line | Count | Source | 167 | 5.35M | pub fn arbitrary<A>(&mut self) -> Result<A> | 168 | 5.35M | where | 169 | 5.35M | A: Arbitrary<'a>, | 170 | | { | 171 | 5.35M | <A as Arbitrary<'a>>::arbitrary(self) | 172 | 5.35M | } |
|
173 | | |
174 | | /// Get the number of elements to insert when building up a collection of |
175 | | /// arbitrary `ElementType`s. |
176 | | /// |
177 | | /// This uses the [`<ElementType as |
178 | | /// Arbitrary>::size_hint`][crate::Arbitrary::size_hint] method to smartly |
179 | | /// choose a length such that we most likely have enough underlying bytes to |
180 | | /// construct that many arbitrary `ElementType`s. |
181 | | /// |
182 | | /// This should only be called within an `Arbitrary` implementation. |
183 | | /// |
184 | | /// # Example |
185 | | /// |
186 | | /// ``` |
187 | | /// use arbitrary::{Arbitrary, Result, Unstructured}; |
188 | | /// # pub struct MyCollection<T> { _t: std::marker::PhantomData<T> } |
189 | | /// # impl<T> MyCollection<T> { |
190 | | /// # pub fn with_capacity(capacity: usize) -> Self { MyCollection { _t: std::marker::PhantomData } } |
191 | | /// # pub fn insert(&mut self, element: T) {} |
192 | | /// # } |
193 | | /// |
194 | | /// impl<'a, T> Arbitrary<'a> for MyCollection<T> |
195 | | /// where |
196 | | /// T: Arbitrary<'a>, |
197 | | /// { |
198 | | /// fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { |
199 | | /// // Get the number of `T`s we should insert into our collection. |
200 | | /// let len = u.arbitrary_len::<T>()?; |
201 | | /// |
202 | | /// // And then create a collection of that length! |
203 | | /// let mut my_collection = MyCollection::with_capacity(len); |
204 | | /// for _ in 0..len { |
205 | | /// let element = T::arbitrary(u)?; |
206 | | /// my_collection.insert(element); |
207 | | /// } |
208 | | /// |
209 | | /// Ok(my_collection) |
210 | | /// } |
211 | | /// } |
212 | | /// ``` |
213 | 15.3k | pub fn arbitrary_len<ElementType>(&mut self) -> Result<usize> |
214 | 15.3k | where |
215 | 15.3k | ElementType: Arbitrary<'a>, |
216 | | { |
217 | 15.3k | let byte_size = self.arbitrary_byte_size()?; |
218 | 15.3k | let (lower, upper) = <ElementType as Arbitrary>::size_hint(0); |
219 | 15.3k | let elem_size = upper.unwrap_or(lower * 2); |
220 | 15.3k | let elem_size = std::cmp::max(1, elem_size); |
221 | 15.3k | Ok(byte_size / elem_size) |
222 | 15.3k | } |
223 | | |
224 | 15.3k | fn arbitrary_byte_size(&mut self) -> Result<usize> { |
225 | 15.3k | if self.data.is_empty() { |
226 | 0 | Ok(0) |
227 | 15.3k | } else if self.data.len() == 1 { |
228 | 0 | self.data = &[]; |
229 | 0 | Ok(0) |
230 | | } else { |
231 | | // Take lengths from the end of the data, since the `libFuzzer` folks |
232 | | // found that this lets fuzzers more efficiently explore the input |
233 | | // space. |
234 | | // |
235 | | // https://github.com/rust-fuzz/libfuzzer-sys/blob/0c450753/libfuzzer/utils/FuzzedDataProvider.h#L92-L97 |
236 | | |
237 | | // We only consume as many bytes as necessary to cover the entire |
238 | | // range of the byte string. |
239 | | // Note: We cast to u64 so we don't overflow when checking std::u32::MAX + 4 on 32-bit archs |
240 | 15.3k | let len = if self.data.len() as u64 <= std::u8::MAX as u64 + 1 { |
241 | 11.0k | let bytes = 1; |
242 | 11.0k | let max_size = self.data.len() - bytes; |
243 | 11.0k | let (rest, for_size) = self.data.split_at(max_size); |
244 | 11.0k | self.data = rest; |
245 | 11.0k | Self::int_in_range_impl(0..=max_size as u8, for_size.iter().copied())?.0 as usize |
246 | 4.27k | } else if self.data.len() as u64 <= std::u16::MAX as u64 + 2 { |
247 | 3.42k | let bytes = 2; |
248 | 3.42k | let max_size = self.data.len() - bytes; |
249 | 3.42k | let (rest, for_size) = self.data.split_at(max_size); |
250 | 3.42k | self.data = rest; |
251 | 3.42k | Self::int_in_range_impl(0..=max_size as u16, for_size.iter().copied())?.0 as usize |
252 | 853 | } else if self.data.len() as u64 <= std::u32::MAX as u64 + 4 { |
253 | 853 | let bytes = 4; |
254 | 853 | let max_size = self.data.len() - bytes; |
255 | 853 | let (rest, for_size) = self.data.split_at(max_size); |
256 | 853 | self.data = rest; |
257 | 853 | Self::int_in_range_impl(0..=max_size as u32, for_size.iter().copied())?.0 as usize |
258 | | } else { |
259 | 0 | let bytes = 8; |
260 | 0 | let max_size = self.data.len() - bytes; |
261 | 0 | let (rest, for_size) = self.data.split_at(max_size); |
262 | 0 | self.data = rest; |
263 | 0 | Self::int_in_range_impl(0..=max_size as u64, for_size.iter().copied())?.0 as usize |
264 | | }; |
265 | | |
266 | 15.3k | Ok(len) |
267 | | } |
268 | 15.3k | } |
269 | | |
270 | | /// Generate an integer within the given range. |
271 | | /// |
272 | | /// Do not use this to generate the size of a collection. Use |
273 | | /// `arbitrary_len` instead. |
274 | | /// |
275 | | /// # Panics |
276 | | /// |
277 | | /// Panics if `range.start > range.end`. That is, the given range must be |
278 | | /// non-empty. |
279 | | /// |
280 | | /// # Example |
281 | | /// |
282 | | /// ``` |
283 | | /// use arbitrary::{Arbitrary, Unstructured}; |
284 | | /// |
285 | | /// let mut u = Unstructured::new(&[1, 2, 3, 4]); |
286 | | /// |
287 | | /// let x: i32 = u.int_in_range(-5_000..=-1_000) |
288 | | /// .expect("constructed `u` with enough bytes to generate an `i32`"); |
289 | | /// |
290 | | /// assert!(-5_000 <= x); |
291 | | /// assert!(x <= -1_000); |
292 | | /// ``` |
293 | 0 | pub fn int_in_range<T>(&mut self, range: ops::RangeInclusive<T>) -> Result<T> |
294 | 0 | where |
295 | 0 | T: Int, |
296 | | { |
297 | 0 | let (result, bytes_consumed) = Self::int_in_range_impl(range, self.data.iter().cloned())?; |
298 | 0 | self.data = &self.data[bytes_consumed..]; |
299 | 0 | Ok(result) |
300 | 0 | } Unexecuted instantiation: <arbitrary::unstructured::Unstructured>::int_in_range::<usize> Unexecuted instantiation: <arbitrary::unstructured::Unstructured>::int_in_range::<u32> |
301 | | |
302 | 15.3k | fn int_in_range_impl<T>( |
303 | 15.3k | range: ops::RangeInclusive<T>, |
304 | 15.3k | mut bytes: impl Iterator<Item = u8>, |
305 | 15.3k | ) -> Result<(T, usize)> |
306 | 15.3k | where |
307 | 15.3k | T: Int, |
308 | | { |
309 | 15.3k | let start = *range.start(); |
310 | 15.3k | let end = *range.end(); |
311 | 15.3k | assert!( |
312 | 15.3k | start <= end, |
313 | 0 | "`arbitrary::Unstructured::int_in_range` requires a non-empty range" |
314 | | ); |
315 | | |
316 | | // When there is only one possible choice, don't waste any entropy from |
317 | | // the underlying data. |
318 | 15.3k | if start == end { |
319 | 0 | return Ok((start, 0)); |
320 | 15.3k | } |
321 | | |
322 | | // From here on out we work with the unsigned representation. All of the |
323 | | // operations performed below work out just as well whether or not `T` |
324 | | // is a signed or unsigned integer. |
325 | 15.3k | let start = start.to_unsigned(); |
326 | 15.3k | let end = end.to_unsigned(); |
327 | | |
328 | 15.3k | let delta = end.wrapping_sub(start); |
329 | 15.3k | debug_assert_ne!(delta, T::Unsigned::ZERO); |
330 | | |
331 | | // Compute an arbitrary integer offset from the start of the range. We |
332 | | // do this by consuming `size_of(T)` bytes from the input to create an |
333 | | // arbitrary integer and then clamping that int into our range bounds |
334 | | // with a modulo operation. |
335 | 15.3k | let mut arbitrary_int = T::Unsigned::ZERO; |
336 | 15.3k | let mut bytes_consumed: usize = 0; |
337 | | |
338 | 35.7k | while (bytes_consumed < mem::size_of::<T>()) |
339 | 21.2k | && (delta >> T::Unsigned::from_usize(bytes_consumed * 8)) > T::Unsigned::ZERO |
340 | | { |
341 | 20.4k | let byte = match bytes.next() { |
342 | 0 | None => break, |
343 | 20.4k | Some(b) => b, |
344 | | }; |
345 | 20.4k | bytes_consumed += 1; |
346 | | |
347 | | // Combine this byte into our arbitrary integer, but avoid |
348 | | // overflowing the shift for `u8` and `i8`. |
349 | 20.4k | arbitrary_int = if mem::size_of::<T>() == 1 { |
350 | 11.0k | T::Unsigned::from_u8(byte) |
351 | | } else { |
352 | 9.34k | (arbitrary_int << 8) | T::Unsigned::from_u8(byte) |
353 | | }; |
354 | | } |
355 | | |
356 | 15.3k | let offset = if delta == T::Unsigned::MAX { |
357 | 82 | arbitrary_int |
358 | | } else { |
359 | 15.2k | arbitrary_int % (delta.checked_add(T::Unsigned::ONE).unwrap()) |
360 | | }; |
361 | | |
362 | | // Finally, we add `start` to our offset from `start` to get the result |
363 | | // actual value within the range. |
364 | 15.3k | let result = start.wrapping_add(offset); |
365 | | |
366 | | // And convert back to our maybe-signed representation. |
367 | 15.3k | let result = T::from_unsigned(result); |
368 | 15.3k | debug_assert!(*range.start() <= result); |
369 | 15.3k | debug_assert!(result <= *range.end()); |
370 | | |
371 | 15.3k | Ok((result, bytes_consumed)) |
372 | 15.3k | } <arbitrary::unstructured::Unstructured>::int_in_range_impl::<u8, core::iter::adapters::copied::Copied<core::slice::iter::Iter<u8>>> Line | Count | Source | 302 | 11.0k | fn int_in_range_impl<T>( | 303 | 11.0k | range: ops::RangeInclusive<T>, | 304 | 11.0k | mut bytes: impl Iterator<Item = u8>, | 305 | 11.0k | ) -> Result<(T, usize)> | 306 | 11.0k | where | 307 | 11.0k | T: Int, | 308 | | { | 309 | 11.0k | let start = *range.start(); | 310 | 11.0k | let end = *range.end(); | 311 | 11.0k | assert!( | 312 | 11.0k | start <= end, | 313 | 0 | "`arbitrary::Unstructured::int_in_range` requires a non-empty range" | 314 | | ); | 315 | | | 316 | | // When there is only one possible choice, don't waste any entropy from | 317 | | // the underlying data. | 318 | 11.0k | if start == end { | 319 | 0 | return Ok((start, 0)); | 320 | 11.0k | } | 321 | | | 322 | | // From here on out we work with the unsigned representation. All of the | 323 | | // operations performed below work out just as well whether or not `T` | 324 | | // is a signed or unsigned integer. | 325 | 11.0k | let start = start.to_unsigned(); | 326 | 11.0k | let end = end.to_unsigned(); | 327 | | | 328 | 11.0k | let delta = end.wrapping_sub(start); | 329 | 11.0k | debug_assert_ne!(delta, T::Unsigned::ZERO); | 330 | | | 331 | | // Compute an arbitrary integer offset from the start of the range. We | 332 | | // do this by consuming `size_of(T)` bytes from the input to create an | 333 | | // arbitrary integer and then clamping that int into our range bounds | 334 | | // with a modulo operation. | 335 | 11.0k | let mut arbitrary_int = T::Unsigned::ZERO; | 336 | 11.0k | let mut bytes_consumed: usize = 0; | 337 | | | 338 | 22.1k | while (bytes_consumed < mem::size_of::<T>()) | 339 | 11.0k | && (delta >> T::Unsigned::from_usize(bytes_consumed * 8)) > T::Unsigned::ZERO | 340 | | { | 341 | 11.0k | let byte = match bytes.next() { | 342 | 0 | None => break, | 343 | 11.0k | Some(b) => b, | 344 | | }; | 345 | 11.0k | bytes_consumed += 1; | 346 | | | 347 | | // Combine this byte into our arbitrary integer, but avoid | 348 | | // overflowing the shift for `u8` and `i8`. | 349 | 11.0k | arbitrary_int = if mem::size_of::<T>() == 1 { | 350 | 11.0k | T::Unsigned::from_u8(byte) | 351 | | } else { | 352 | 0 | (arbitrary_int << 8) | T::Unsigned::from_u8(byte) | 353 | | }; | 354 | | } | 355 | | | 356 | 11.0k | let offset = if delta == T::Unsigned::MAX { | 357 | 64 | arbitrary_int | 358 | | } else { | 359 | 11.0k | arbitrary_int % (delta.checked_add(T::Unsigned::ONE).unwrap()) | 360 | | }; | 361 | | | 362 | | // Finally, we add `start` to our offset from `start` to get the result | 363 | | // actual value within the range. | 364 | 11.0k | let result = start.wrapping_add(offset); | 365 | | | 366 | | // And convert back to our maybe-signed representation. | 367 | 11.0k | let result = T::from_unsigned(result); | 368 | 11.0k | debug_assert!(*range.start() <= result); | 369 | 11.0k | debug_assert!(result <= *range.end()); | 370 | | | 371 | 11.0k | Ok((result, bytes_consumed)) | 372 | 11.0k | } |
Unexecuted instantiation: <arbitrary::unstructured::Unstructured>::int_in_range_impl::<usize, core::iter::adapters::cloned::Cloned<core::slice::iter::Iter<u8>>> Unexecuted instantiation: <arbitrary::unstructured::Unstructured>::int_in_range_impl::<u32, core::iter::adapters::cloned::Cloned<core::slice::iter::Iter<u8>>> <arbitrary::unstructured::Unstructured>::int_in_range_impl::<u32, core::iter::adapters::copied::Copied<core::slice::iter::Iter<u8>>> Line | Count | Source | 302 | 853 | fn int_in_range_impl<T>( | 303 | 853 | range: ops::RangeInclusive<T>, | 304 | 853 | mut bytes: impl Iterator<Item = u8>, | 305 | 853 | ) -> Result<(T, usize)> | 306 | 853 | where | 307 | 853 | T: Int, | 308 | | { | 309 | 853 | let start = *range.start(); | 310 | 853 | let end = *range.end(); | 311 | 853 | assert!( | 312 | 853 | start <= end, | 313 | 0 | "`arbitrary::Unstructured::int_in_range` requires a non-empty range" | 314 | | ); | 315 | | | 316 | | // When there is only one possible choice, don't waste any entropy from | 317 | | // the underlying data. | 318 | 853 | if start == end { | 319 | 0 | return Ok((start, 0)); | 320 | 853 | } | 321 | | | 322 | | // From here on out we work with the unsigned representation. All of the | 323 | | // operations performed below work out just as well whether or not `T` | 324 | | // is a signed or unsigned integer. | 325 | 853 | let start = start.to_unsigned(); | 326 | 853 | let end = end.to_unsigned(); | 327 | | | 328 | 853 | let delta = end.wrapping_sub(start); | 329 | 853 | debug_assert_ne!(delta, T::Unsigned::ZERO); | 330 | | | 331 | | // Compute an arbitrary integer offset from the start of the range. We | 332 | | // do this by consuming `size_of(T)` bytes from the input to create an | 333 | | // arbitrary integer and then clamping that int into our range bounds | 334 | | // with a modulo operation. | 335 | 853 | let mut arbitrary_int = T::Unsigned::ZERO; | 336 | 853 | let mut bytes_consumed: usize = 0; | 337 | | | 338 | 3.38k | while (bytes_consumed < mem::size_of::<T>()) | 339 | 3.38k | && (delta >> T::Unsigned::from_usize(bytes_consumed * 8)) > T::Unsigned::ZERO | 340 | | { | 341 | 2.53k | let byte = match bytes.next() { | 342 | 0 | None => break, | 343 | 2.53k | Some(b) => b, | 344 | | }; | 345 | 2.53k | bytes_consumed += 1; | 346 | | | 347 | | // Combine this byte into our arbitrary integer, but avoid | 348 | | // overflowing the shift for `u8` and `i8`. | 349 | 2.53k | arbitrary_int = if mem::size_of::<T>() == 1 { | 350 | 0 | T::Unsigned::from_u8(byte) | 351 | | } else { | 352 | 2.53k | (arbitrary_int << 8) | T::Unsigned::from_u8(byte) | 353 | | }; | 354 | | } | 355 | | | 356 | 853 | let offset = if delta == T::Unsigned::MAX { | 357 | 0 | arbitrary_int | 358 | | } else { | 359 | 853 | arbitrary_int % (delta.checked_add(T::Unsigned::ONE).unwrap()) | 360 | | }; | 361 | | | 362 | | // Finally, we add `start` to our offset from `start` to get the result | 363 | | // actual value within the range. | 364 | 853 | let result = start.wrapping_add(offset); | 365 | | | 366 | | // And convert back to our maybe-signed representation. | 367 | 853 | let result = T::from_unsigned(result); | 368 | 853 | debug_assert!(*range.start() <= result); | 369 | 853 | debug_assert!(result <= *range.end()); | 370 | | | 371 | 853 | Ok((result, bytes_consumed)) | 372 | 853 | } |
<arbitrary::unstructured::Unstructured>::int_in_range_impl::<u16, core::iter::adapters::copied::Copied<core::slice::iter::Iter<u8>>> Line | Count | Source | 302 | 3.42k | fn int_in_range_impl<T>( | 303 | 3.42k | range: ops::RangeInclusive<T>, | 304 | 3.42k | mut bytes: impl Iterator<Item = u8>, | 305 | 3.42k | ) -> Result<(T, usize)> | 306 | 3.42k | where | 307 | 3.42k | T: Int, | 308 | | { | 309 | 3.42k | let start = *range.start(); | 310 | 3.42k | let end = *range.end(); | 311 | 3.42k | assert!( | 312 | 3.42k | start <= end, | 313 | 0 | "`arbitrary::Unstructured::int_in_range` requires a non-empty range" | 314 | | ); | 315 | | | 316 | | // When there is only one possible choice, don't waste any entropy from | 317 | | // the underlying data. | 318 | 3.42k | if start == end { | 319 | 0 | return Ok((start, 0)); | 320 | 3.42k | } | 321 | | | 322 | | // From here on out we work with the unsigned representation. All of the | 323 | | // operations performed below work out just as well whether or not `T` | 324 | | // is a signed or unsigned integer. | 325 | 3.42k | let start = start.to_unsigned(); | 326 | 3.42k | let end = end.to_unsigned(); | 327 | | | 328 | 3.42k | let delta = end.wrapping_sub(start); | 329 | 3.42k | debug_assert_ne!(delta, T::Unsigned::ZERO); | 330 | | | 331 | | // Compute an arbitrary integer offset from the start of the range. We | 332 | | // do this by consuming `size_of(T)` bytes from the input to create an | 333 | | // arbitrary integer and then clamping that int into our range bounds | 334 | | // with a modulo operation. | 335 | 3.42k | let mut arbitrary_int = T::Unsigned::ZERO; | 336 | 3.42k | let mut bytes_consumed: usize = 0; | 337 | | | 338 | 10.2k | while (bytes_consumed < mem::size_of::<T>()) | 339 | 6.84k | && (delta >> T::Unsigned::from_usize(bytes_consumed * 8)) > T::Unsigned::ZERO | 340 | | { | 341 | 6.81k | let byte = match bytes.next() { | 342 | 0 | None => break, | 343 | 6.81k | Some(b) => b, | 344 | | }; | 345 | 6.81k | bytes_consumed += 1; | 346 | | | 347 | | // Combine this byte into our arbitrary integer, but avoid | 348 | | // overflowing the shift for `u8` and `i8`. | 349 | 6.81k | arbitrary_int = if mem::size_of::<T>() == 1 { | 350 | 0 | T::Unsigned::from_u8(byte) | 351 | | } else { | 352 | 6.81k | (arbitrary_int << 8) | T::Unsigned::from_u8(byte) | 353 | | }; | 354 | | } | 355 | | | 356 | 3.42k | let offset = if delta == T::Unsigned::MAX { | 357 | 18 | arbitrary_int | 358 | | } else { | 359 | 3.40k | arbitrary_int % (delta.checked_add(T::Unsigned::ONE).unwrap()) | 360 | | }; | 361 | | | 362 | | // Finally, we add `start` to our offset from `start` to get the result | 363 | | // actual value within the range. | 364 | 3.42k | let result = start.wrapping_add(offset); | 365 | | | 366 | | // And convert back to our maybe-signed representation. | 367 | 3.42k | let result = T::from_unsigned(result); | 368 | 3.42k | debug_assert!(*range.start() <= result); | 369 | 3.42k | debug_assert!(result <= *range.end()); | 370 | | | 371 | 3.42k | Ok((result, bytes_consumed)) | 372 | 3.42k | } |
Unexecuted instantiation: <arbitrary::unstructured::Unstructured>::int_in_range_impl::<u64, core::iter::adapters::copied::Copied<core::slice::iter::Iter<u8>>> |
373 | | |
374 | | /// Choose one of the given choices. |
375 | | /// |
376 | | /// This should only be used inside of `Arbitrary` implementations. |
377 | | /// |
378 | | /// Returns an error if there is not enough underlying data to make a |
379 | | /// choice or if no choices are provided. |
380 | | /// |
381 | | /// # Examples |
382 | | /// |
383 | | /// Selecting from an array of choices: |
384 | | /// |
385 | | /// ``` |
386 | | /// use arbitrary::Unstructured; |
387 | | /// |
388 | | /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); |
389 | | /// let choices = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; |
390 | | /// |
391 | | /// let choice = u.choose(&choices).unwrap(); |
392 | | /// |
393 | | /// println!("chose {}", choice); |
394 | | /// ``` |
395 | | /// |
396 | | /// An error is returned if no choices are provided: |
397 | | /// |
398 | | /// ``` |
399 | | /// use arbitrary::Unstructured; |
400 | | /// |
401 | | /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); |
402 | | /// let choices: [char; 0] = []; |
403 | | /// |
404 | | /// let result = u.choose(&choices); |
405 | | /// |
406 | | /// assert!(result.is_err()); |
407 | | /// ``` |
408 | 0 | pub fn choose<'b, T>(&mut self, choices: &'b [T]) -> Result<&'b T> { |
409 | 0 | let idx = self.choose_index(choices.len())?; |
410 | 0 | Ok(&choices[idx]) |
411 | 0 | } |
412 | | |
413 | | /// Choose a value in `0..len`. |
414 | | /// |
415 | | /// Returns an error if the `len` is zero. |
416 | | /// |
417 | | /// # Examples |
418 | | /// |
419 | | /// Using Fisher–Yates shuffle shuffle to gerate an arbitrary permutation. |
420 | | /// |
421 | | /// [Fisher–Yates shuffle]: https://en.wikipedia.org/wiki/Fisher–Yates_shuffle |
422 | | /// |
423 | | /// ``` |
424 | | /// use arbitrary::Unstructured; |
425 | | /// |
426 | | /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); |
427 | | /// let mut permutation = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; |
428 | | /// let mut to_permute = &mut permutation[..]; |
429 | | /// while to_permute.len() > 1 { |
430 | | /// let idx = u.choose_index(to_permute.len()).unwrap(); |
431 | | /// to_permute.swap(0, idx); |
432 | | /// to_permute = &mut to_permute[1..]; |
433 | | /// } |
434 | | /// |
435 | | /// println!("permutation: {:?}", permutation); |
436 | | /// ``` |
437 | | /// |
438 | | /// An error is returned if the length is zero: |
439 | | /// |
440 | | /// ``` |
441 | | /// use arbitrary::Unstructured; |
442 | | /// |
443 | | /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); |
444 | | /// let array: [i32; 0] = []; |
445 | | /// |
446 | | /// let result = u.choose_index(array.len()); |
447 | | /// |
448 | | /// assert!(result.is_err()); |
449 | | /// ``` |
450 | 0 | pub fn choose_index(&mut self, len: usize) -> Result<usize> { |
451 | 0 | if len == 0 { |
452 | 0 | return Err(Error::EmptyChoose); |
453 | 0 | } |
454 | 0 | let idx = self.int_in_range(0..=len - 1)?; |
455 | 0 | Ok(idx) |
456 | 0 | } |
457 | | |
458 | | /// Generate a boolean according to the given ratio. |
459 | | /// |
460 | | /// # Panics |
461 | | /// |
462 | | /// Panics when the numerator and denominator do not meet these constraints: |
463 | | /// |
464 | | /// * `0 < numerator <= denominator` |
465 | | /// |
466 | | /// # Example |
467 | | /// |
468 | | /// Generate a boolean that is `true` five sevenths of the time: |
469 | | /// |
470 | | /// ``` |
471 | | /// # fn foo() -> arbitrary::Result<()> { |
472 | | /// use arbitrary::Unstructured; |
473 | | /// |
474 | | /// # let my_data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; |
475 | | /// let mut u = Unstructured::new(&my_data); |
476 | | /// |
477 | | /// if u.ratio(5, 7)? { |
478 | | /// // Take this branch 5/7 of the time. |
479 | | /// } |
480 | | /// # Ok(()) |
481 | | /// # } |
482 | | /// ``` |
483 | 0 | pub fn ratio<T>(&mut self, numerator: T, denominator: T) -> Result<bool> |
484 | 0 | where |
485 | 0 | T: Int, |
486 | | { |
487 | 0 | assert!(T::ZERO < numerator); |
488 | 0 | assert!(numerator <= denominator); |
489 | 0 | let x = self.int_in_range(T::ONE..=denominator)?; |
490 | 0 | Ok(x <= numerator) |
491 | 0 | } |
492 | | |
493 | | /// Fill a `buffer` with bytes from the underlying raw data. |
494 | | /// |
495 | | /// This should only be called within an `Arbitrary` implementation. This is |
496 | | /// a very low-level operation. You should generally prefer calling nested |
497 | | /// `Arbitrary` implementations like `<Vec<u8>>::arbitrary` and |
498 | | /// `String::arbitrary` over using this method directly. |
499 | | /// |
500 | | /// If this `Unstructured` does not have enough underlying data to fill the |
501 | | /// whole `buffer`, it pads the buffer out with zeros. |
502 | | /// |
503 | | /// # Example |
504 | | /// |
505 | | /// ``` |
506 | | /// use arbitrary::Unstructured; |
507 | | /// |
508 | | /// let mut u = Unstructured::new(&[1, 2, 3, 4]); |
509 | | /// |
510 | | /// let mut buf = [0; 2]; |
511 | | /// |
512 | | /// assert!(u.fill_buffer(&mut buf).is_ok()); |
513 | | /// assert_eq!(buf, [1, 2]); |
514 | | /// |
515 | | /// assert!(u.fill_buffer(&mut buf).is_ok()); |
516 | | /// assert_eq!(buf, [3, 4]); |
517 | | /// |
518 | | /// assert!(u.fill_buffer(&mut buf).is_ok()); |
519 | | /// assert_eq!(buf, [0, 0]); |
520 | | /// ``` |
521 | 21.4M | pub fn fill_buffer(&mut self, buffer: &mut [u8]) -> Result<()> { |
522 | 21.4M | let n = std::cmp::min(buffer.len(), self.data.len()); |
523 | 21.4M | buffer[..n].copy_from_slice(&self.data[..n]); |
524 | 21.4M | for byte in buffer[n..].iter_mut() { |
525 | 158k | *byte = 0; |
526 | 158k | } |
527 | 21.4M | self.data = &self.data[n..]; |
528 | 21.4M | Ok(()) |
529 | 21.4M | } |
530 | | |
531 | | /// Provide `size` bytes from the underlying raw data. |
532 | | /// |
533 | | /// This should only be called within an `Arbitrary` implementation. This is |
534 | | /// a very low-level operation. You should generally prefer calling nested |
535 | | /// `Arbitrary` implementations like `<Vec<u8>>::arbitrary` and |
536 | | /// `String::arbitrary` over using this method directly. |
537 | | /// |
538 | | /// # Example |
539 | | /// |
540 | | /// ``` |
541 | | /// use arbitrary::Unstructured; |
542 | | /// |
543 | | /// let mut u = Unstructured::new(&[1, 2, 3, 4]); |
544 | | /// |
545 | | /// assert!(u.bytes(2).unwrap() == &[1, 2]); |
546 | | /// assert!(u.bytes(2).unwrap() == &[3, 4]); |
547 | | /// ``` |
548 | 17.1k | pub fn bytes(&mut self, size: usize) -> Result<&'a [u8]> { |
549 | 17.1k | if self.data.len() < size { |
550 | 0 | return Err(Error::NotEnoughData); |
551 | 17.1k | } |
552 | | |
553 | 17.1k | let (for_buf, rest) = self.data.split_at(size); |
554 | 17.1k | self.data = rest; |
555 | 17.1k | Ok(for_buf) |
556 | 17.1k | } |
557 | | |
558 | | /// Peek at `size` number of bytes of the underlying raw input. |
559 | | /// |
560 | | /// Does not consume the bytes, only peeks at them. |
561 | | /// |
562 | | /// Returns `None` if there are not `size` bytes left in the underlying raw |
563 | | /// input. |
564 | | /// |
565 | | /// # Example |
566 | | /// |
567 | | /// ``` |
568 | | /// use arbitrary::Unstructured; |
569 | | /// |
570 | | /// let u = Unstructured::new(&[1, 2, 3]); |
571 | | /// |
572 | | /// assert_eq!(u.peek_bytes(0).unwrap(), []); |
573 | | /// assert_eq!(u.peek_bytes(1).unwrap(), [1]); |
574 | | /// assert_eq!(u.peek_bytes(2).unwrap(), [1, 2]); |
575 | | /// assert_eq!(u.peek_bytes(3).unwrap(), [1, 2, 3]); |
576 | | /// |
577 | | /// assert!(u.peek_bytes(4).is_none()); |
578 | | /// ``` |
579 | 17.1k | pub fn peek_bytes(&self, size: usize) -> Option<&'a [u8]> { |
580 | 17.1k | self.data.get(..size) |
581 | 17.1k | } |
582 | | |
583 | | /// Consume all of the rest of the remaining underlying bytes. |
584 | | /// |
585 | | /// Returns a slice of all the remaining, unconsumed bytes. |
586 | | /// |
587 | | /// # Example |
588 | | /// |
589 | | /// ``` |
590 | | /// use arbitrary::Unstructured; |
591 | | /// |
592 | | /// let mut u = Unstructured::new(&[1, 2, 3]); |
593 | | /// |
594 | | /// let mut remaining = u.take_rest(); |
595 | | /// |
596 | | /// assert_eq!(remaining, [1, 2, 3]); |
597 | | /// ``` |
598 | 0 | pub fn take_rest(mut self) -> &'a [u8] { |
599 | 0 | mem::take(&mut self.data) |
600 | 0 | } |
601 | | |
602 | | /// Provide an iterator over elements for constructing a collection |
603 | | /// |
604 | | /// This is useful for implementing [`Arbitrary::arbitrary`] on collections |
605 | | /// since the implementation is simply `u.arbitrary_iter()?.collect()` |
606 | 1.47k | pub fn arbitrary_iter<'b, ElementType: Arbitrary<'a>>( |
607 | 1.47k | &'b mut self, |
608 | 1.47k | ) -> Result<ArbitraryIter<'a, 'b, ElementType>> { |
609 | 1.47k | Ok(ArbitraryIter { |
610 | 1.47k | u: &mut *self, |
611 | 1.47k | _marker: PhantomData, |
612 | 1.47k | }) |
613 | 1.47k | } Unexecuted instantiation: <arbitrary::unstructured::Unstructured>::arbitrary_iter::<u8> <arbitrary::unstructured::Unstructured>::arbitrary_iter::<wrap_optimal_fit_usize::Word> Line | Count | Source | 606 | 741 | pub fn arbitrary_iter<'b, ElementType: Arbitrary<'a>>( | 607 | 741 | &'b mut self, | 608 | 741 | ) -> Result<ArbitraryIter<'a, 'b, ElementType>> { | 609 | 741 | Ok(ArbitraryIter { | 610 | 741 | u: &mut *self, | 611 | 741 | _marker: PhantomData, | 612 | 741 | }) | 613 | 741 | } |
<arbitrary::unstructured::Unstructured>::arbitrary_iter::<wrap_optimal_fit::Word> Line | Count | Source | 606 | 737 | pub fn arbitrary_iter<'b, ElementType: Arbitrary<'a>>( | 607 | 737 | &'b mut self, | 608 | 737 | ) -> Result<ArbitraryIter<'a, 'b, ElementType>> { | 609 | 737 | Ok(ArbitraryIter { | 610 | 737 | u: &mut *self, | 611 | 737 | _marker: PhantomData, | 612 | 737 | }) | 613 | 737 | } |
|
614 | | |
615 | | /// Provide an iterator over elements for constructing a collection from |
616 | | /// all the remaining bytes. |
617 | | /// |
618 | | /// This is useful for implementing [`Arbitrary::arbitrary_take_rest`] on collections |
619 | | /// since the implementation is simply `u.arbitrary_take_rest_iter()?.collect()` |
620 | 309 | pub fn arbitrary_take_rest_iter<ElementType: Arbitrary<'a>>( |
621 | 309 | self, |
622 | 309 | ) -> Result<ArbitraryTakeRestIter<'a, ElementType>> { |
623 | 309 | Ok(ArbitraryTakeRestIter { |
624 | 309 | u: self, |
625 | 309 | _marker: PhantomData, |
626 | 309 | }) |
627 | 309 | } Unexecuted instantiation: <arbitrary::unstructured::Unstructured>::arbitrary_take_rest_iter::<_> <arbitrary::unstructured::Unstructured>::arbitrary_take_rest_iter::<wrap_first_fit::Word> Line | Count | Source | 620 | 309 | pub fn arbitrary_take_rest_iter<ElementType: Arbitrary<'a>>( | 621 | 309 | self, | 622 | 309 | ) -> Result<ArbitraryTakeRestIter<'a, ElementType>> { | 623 | 309 | Ok(ArbitraryTakeRestIter { | 624 | 309 | u: self, | 625 | 309 | _marker: PhantomData, | 626 | 309 | }) | 627 | 309 | } |
|
628 | | |
629 | | /// Call the given function an arbitrary number of times. |
630 | | /// |
631 | | /// The function is given this `Unstructured` so that it can continue to |
632 | | /// generate arbitrary data and structures. |
633 | | /// |
634 | | /// You may optionaly specify minimum and maximum bounds on the number of |
635 | | /// times the function is called. |
636 | | /// |
637 | | /// You may break out of the loop early by returning |
638 | | /// `Ok(std::ops::ControlFlow::Break)`. To continue the loop, return |
639 | | /// `Ok(std::ops::ControlFlow::Continue)`. |
640 | | /// |
641 | | /// # Panics |
642 | | /// |
643 | | /// Panics if `min > max`. |
644 | | /// |
645 | | /// # Example |
646 | | /// |
647 | | /// Call a closure that generates an arbitrary type inside a context an |
648 | | /// arbitrary number of times: |
649 | | /// |
650 | | /// ``` |
651 | | /// use arbitrary::{Result, Unstructured}; |
652 | | /// use std::ops::ControlFlow; |
653 | | /// |
654 | | /// enum Type { |
655 | | /// /// A boolean type. |
656 | | /// Bool, |
657 | | /// |
658 | | /// /// An integer type. |
659 | | /// Int, |
660 | | /// |
661 | | /// /// A list of the `i`th type in this type's context. |
662 | | /// List(usize), |
663 | | /// } |
664 | | /// |
665 | | /// fn arbitrary_types_context(u: &mut Unstructured) -> Result<Vec<Type>> { |
666 | | /// let mut context = vec![]; |
667 | | /// |
668 | | /// u.arbitrary_loop(Some(10), Some(20), |u| { |
669 | | /// let num_choices = if context.is_empty() { |
670 | | /// 2 |
671 | | /// } else { |
672 | | /// 3 |
673 | | /// }; |
674 | | /// let ty = match u.int_in_range::<u8>(1..=num_choices)? { |
675 | | /// 1 => Type::Bool, |
676 | | /// 2 => Type::Int, |
677 | | /// 3 => Type::List(u.int_in_range(0..=context.len() - 1)?), |
678 | | /// _ => unreachable!(), |
679 | | /// }; |
680 | | /// context.push(ty); |
681 | | /// Ok(ControlFlow::Continue(())) |
682 | | /// })?; |
683 | | /// |
684 | | /// // The number of loop iterations are constrained by the min/max |
685 | | /// // bounds that we provided. |
686 | | /// assert!(context.len() >= 10); |
687 | | /// assert!(context.len() <= 20); |
688 | | /// |
689 | | /// Ok(context) |
690 | | /// } |
691 | | /// ``` |
692 | 0 | pub fn arbitrary_loop( |
693 | 0 | &mut self, |
694 | 0 | min: Option<u32>, |
695 | 0 | max: Option<u32>, |
696 | 0 | mut f: impl FnMut(&mut Self) -> Result<ControlFlow<(), ()>>, |
697 | 0 | ) -> Result<()> { |
698 | 0 | let min = min.unwrap_or(0); |
699 | 0 | let max = max.unwrap_or(u32::MAX); |
700 | | |
701 | 0 | for _ in 0..self.int_in_range(min..=max)? { |
702 | 0 | match f(self)? { |
703 | 0 | ControlFlow::Continue(_) => continue, |
704 | 0 | ControlFlow::Break(_) => break, |
705 | | } |
706 | | } |
707 | | |
708 | 0 | Ok(()) |
709 | 0 | } |
710 | | } |
711 | | |
712 | | /// Utility iterator produced by [`Unstructured::arbitrary_iter`] |
713 | | pub struct ArbitraryIter<'a, 'b, ElementType> { |
714 | | u: &'b mut Unstructured<'a>, |
715 | | _marker: PhantomData<ElementType>, |
716 | | } |
717 | | |
718 | | impl<'a, 'b, ElementType: Arbitrary<'a>> Iterator for ArbitraryIter<'a, 'b, ElementType> { |
719 | | type Item = Result<ElementType>; |
720 | 4.38M | fn next(&mut self) -> Option<Result<ElementType>> { |
721 | 4.38M | let keep_going = self.u.arbitrary().unwrap_or(false); |
722 | 4.38M | if keep_going { |
723 | 4.38M | Some(Arbitrary::arbitrary(self.u)) |
724 | | } else { |
725 | 1.47k | None |
726 | | } |
727 | 4.38M | } Unexecuted instantiation: <arbitrary::unstructured::ArbitraryIter<u8> as core::iter::traits::iterator::Iterator>::next <arbitrary::unstructured::ArbitraryIter<wrap_optimal_fit_usize::Word> as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 720 | 2.28M | fn next(&mut self) -> Option<Result<ElementType>> { | 721 | 2.28M | let keep_going = self.u.arbitrary().unwrap_or(false); | 722 | 2.28M | if keep_going { | 723 | 2.28M | Some(Arbitrary::arbitrary(self.u)) | 724 | | } else { | 725 | 741 | None | 726 | | } | 727 | 2.28M | } |
<arbitrary::unstructured::ArbitraryIter<wrap_optimal_fit::Word> as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 720 | 2.09M | fn next(&mut self) -> Option<Result<ElementType>> { | 721 | 2.09M | let keep_going = self.u.arbitrary().unwrap_or(false); | 722 | 2.09M | if keep_going { | 723 | 2.09M | Some(Arbitrary::arbitrary(self.u)) | 724 | | } else { | 725 | 737 | None | 726 | | } | 727 | 2.09M | } |
|
728 | | } |
729 | | |
730 | | /// Utility iterator produced by [`Unstructured::arbitrary_take_rest_iter`] |
731 | | pub struct ArbitraryTakeRestIter<'a, ElementType> { |
732 | | u: Unstructured<'a>, |
733 | | _marker: PhantomData<ElementType>, |
734 | | } |
735 | | |
736 | | impl<'a, ElementType: Arbitrary<'a>> Iterator for ArbitraryTakeRestIter<'a, ElementType> { |
737 | | type Item = Result<ElementType>; |
738 | 968k | fn next(&mut self) -> Option<Result<ElementType>> { |
739 | 968k | let keep_going = self.u.arbitrary().unwrap_or(false); |
740 | 968k | if keep_going { |
741 | 967k | Some(Arbitrary::arbitrary(&mut self.u)) |
742 | | } else { |
743 | 309 | None |
744 | | } |
745 | 968k | } Unexecuted instantiation: <arbitrary::unstructured::ArbitraryTakeRestIter<_> as core::iter::traits::iterator::Iterator>::next <arbitrary::unstructured::ArbitraryTakeRestIter<wrap_first_fit::Word> as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 738 | 968k | fn next(&mut self) -> Option<Result<ElementType>> { | 739 | 968k | let keep_going = self.u.arbitrary().unwrap_or(false); | 740 | 968k | if keep_going { | 741 | 967k | Some(Arbitrary::arbitrary(&mut self.u)) | 742 | | } else { | 743 | 309 | None | 744 | | } | 745 | 968k | } |
|
746 | | } |
747 | | |
748 | | /// A trait that is implemented for all of the primitive integers: |
749 | | /// |
750 | | /// * `u8` |
751 | | /// * `u16` |
752 | | /// * `u32` |
753 | | /// * `u64` |
754 | | /// * `u128` |
755 | | /// * `usize` |
756 | | /// * `i8` |
757 | | /// * `i16` |
758 | | /// * `i32` |
759 | | /// * `i64` |
760 | | /// * `i128` |
761 | | /// * `isize` |
762 | | /// |
763 | | /// Don't implement this trait yourself. |
764 | | pub trait Int: |
765 | | Copy |
766 | | + std::fmt::Debug |
767 | | + PartialOrd |
768 | | + Ord |
769 | | + ops::Sub<Self, Output = Self> |
770 | | + ops::Rem<Self, Output = Self> |
771 | | + ops::Shr<Self, Output = Self> |
772 | | + ops::Shl<usize, Output = Self> |
773 | | + ops::BitOr<Self, Output = Self> |
774 | | { |
775 | | #[doc(hidden)] |
776 | | type Unsigned: Int; |
777 | | |
778 | | #[doc(hidden)] |
779 | | const ZERO: Self; |
780 | | |
781 | | #[doc(hidden)] |
782 | | const ONE: Self; |
783 | | |
784 | | #[doc(hidden)] |
785 | | const MAX: Self; |
786 | | |
787 | | #[doc(hidden)] |
788 | | fn from_u8(b: u8) -> Self; |
789 | | |
790 | | #[doc(hidden)] |
791 | | fn from_usize(u: usize) -> Self; |
792 | | |
793 | | #[doc(hidden)] |
794 | | fn checked_add(self, rhs: Self) -> Option<Self>; |
795 | | |
796 | | #[doc(hidden)] |
797 | | fn wrapping_add(self, rhs: Self) -> Self; |
798 | | |
799 | | #[doc(hidden)] |
800 | | fn wrapping_sub(self, rhs: Self) -> Self; |
801 | | |
802 | | #[doc(hidden)] |
803 | | fn to_unsigned(self) -> Self::Unsigned; |
804 | | |
805 | | #[doc(hidden)] |
806 | | fn from_unsigned(unsigned: Self::Unsigned) -> Self; |
807 | | } |
808 | | |
809 | | macro_rules! impl_int { |
810 | | ( $( $ty:ty : $unsigned_ty: ty ; )* ) => { |
811 | | $( |
812 | | impl Int for $ty { |
813 | | type Unsigned = $unsigned_ty; |
814 | | |
815 | | const ZERO: Self = 0; |
816 | | |
817 | | const ONE: Self = 1; |
818 | | |
819 | | const MAX: Self = Self::MAX; |
820 | | |
821 | 20.4k | fn from_u8(b: u8) -> Self { |
822 | 11.0k | b as Self |
823 | 20.4k | } <u8 as arbitrary::unstructured::Int>::from_u8 Line | Count | Source | 821 | 11.0k | fn from_u8(b: u8) -> Self { | 822 | 11.0k | b as Self | 823 | 11.0k | } |
<u16 as arbitrary::unstructured::Int>::from_u8 Line | Count | Source | 821 | 6.81k | fn from_u8(b: u8) -> Self { | 822 | 6.81k | b as Self | 823 | 6.81k | } |
<u32 as arbitrary::unstructured::Int>::from_u8 Line | Count | Source | 821 | 2.53k | fn from_u8(b: u8) -> Self { | 822 | 2.53k | b as Self | 823 | 2.53k | } |
Unexecuted instantiation: <u64 as arbitrary::unstructured::Int>::from_u8 Unexecuted instantiation: <u128 as arbitrary::unstructured::Int>::from_u8 Unexecuted instantiation: <usize as arbitrary::unstructured::Int>::from_u8 Unexecuted instantiation: <i8 as arbitrary::unstructured::Int>::from_u8 Unexecuted instantiation: <i16 as arbitrary::unstructured::Int>::from_u8 Unexecuted instantiation: <i32 as arbitrary::unstructured::Int>::from_u8 Unexecuted instantiation: <i64 as arbitrary::unstructured::Int>::from_u8 Unexecuted instantiation: <i128 as arbitrary::unstructured::Int>::from_u8 Unexecuted instantiation: <isize as arbitrary::unstructured::Int>::from_u8 |
824 | | |
825 | 21.2k | fn from_usize(u: usize) -> Self { |
826 | 0 | u as Self |
827 | 21.2k | } <u8 as arbitrary::unstructured::Int>::from_usize Line | Count | Source | 825 | 11.0k | fn from_usize(u: usize) -> Self { | 826 | 11.0k | u as Self | 827 | 11.0k | } |
<u16 as arbitrary::unstructured::Int>::from_usize Line | Count | Source | 825 | 6.84k | fn from_usize(u: usize) -> Self { | 826 | 6.84k | u as Self | 827 | 6.84k | } |
<u32 as arbitrary::unstructured::Int>::from_usize Line | Count | Source | 825 | 3.38k | fn from_usize(u: usize) -> Self { | 826 | 3.38k | u as Self | 827 | 3.38k | } |
Unexecuted instantiation: <u64 as arbitrary::unstructured::Int>::from_usize Unexecuted instantiation: <u128 as arbitrary::unstructured::Int>::from_usize Unexecuted instantiation: <usize as arbitrary::unstructured::Int>::from_usize Unexecuted instantiation: <i8 as arbitrary::unstructured::Int>::from_usize Unexecuted instantiation: <i16 as arbitrary::unstructured::Int>::from_usize Unexecuted instantiation: <i32 as arbitrary::unstructured::Int>::from_usize Unexecuted instantiation: <i64 as arbitrary::unstructured::Int>::from_usize Unexecuted instantiation: <i128 as arbitrary::unstructured::Int>::from_usize Unexecuted instantiation: <isize as arbitrary::unstructured::Int>::from_usize |
828 | | |
829 | 15.2k | fn checked_add(self, rhs: Self) -> Option<Self> { |
830 | 15.2k | <$ty>::checked_add(self, rhs) |
831 | 15.2k | } <u8 as arbitrary::unstructured::Int>::checked_add Line | Count | Source | 829 | 11.0k | fn checked_add(self, rhs: Self) -> Option<Self> { | 830 | 11.0k | <$ty>::checked_add(self, rhs) | 831 | 11.0k | } |
<u16 as arbitrary::unstructured::Int>::checked_add Line | Count | Source | 829 | 3.40k | fn checked_add(self, rhs: Self) -> Option<Self> { | 830 | 3.40k | <$ty>::checked_add(self, rhs) | 831 | 3.40k | } |
<u32 as arbitrary::unstructured::Int>::checked_add Line | Count | Source | 829 | 853 | fn checked_add(self, rhs: Self) -> Option<Self> { | 830 | 853 | <$ty>::checked_add(self, rhs) | 831 | 853 | } |
Unexecuted instantiation: <u64 as arbitrary::unstructured::Int>::checked_add Unexecuted instantiation: <u128 as arbitrary::unstructured::Int>::checked_add Unexecuted instantiation: <usize as arbitrary::unstructured::Int>::checked_add Unexecuted instantiation: <i8 as arbitrary::unstructured::Int>::checked_add Unexecuted instantiation: <i16 as arbitrary::unstructured::Int>::checked_add Unexecuted instantiation: <i32 as arbitrary::unstructured::Int>::checked_add Unexecuted instantiation: <i64 as arbitrary::unstructured::Int>::checked_add Unexecuted instantiation: <i128 as arbitrary::unstructured::Int>::checked_add Unexecuted instantiation: <isize as arbitrary::unstructured::Int>::checked_add |
832 | | |
833 | 15.3k | fn wrapping_add(self, rhs: Self) -> Self { |
834 | 15.3k | <$ty>::wrapping_add(self, rhs) |
835 | 15.3k | } <u8 as arbitrary::unstructured::Int>::wrapping_add Line | Count | Source | 833 | 11.0k | fn wrapping_add(self, rhs: Self) -> Self { | 834 | 11.0k | <$ty>::wrapping_add(self, rhs) | 835 | 11.0k | } |
<u16 as arbitrary::unstructured::Int>::wrapping_add Line | Count | Source | 833 | 3.42k | fn wrapping_add(self, rhs: Self) -> Self { | 834 | 3.42k | <$ty>::wrapping_add(self, rhs) | 835 | 3.42k | } |
<u32 as arbitrary::unstructured::Int>::wrapping_add Line | Count | Source | 833 | 853 | fn wrapping_add(self, rhs: Self) -> Self { | 834 | 853 | <$ty>::wrapping_add(self, rhs) | 835 | 853 | } |
Unexecuted instantiation: <u64 as arbitrary::unstructured::Int>::wrapping_add Unexecuted instantiation: <u128 as arbitrary::unstructured::Int>::wrapping_add Unexecuted instantiation: <usize as arbitrary::unstructured::Int>::wrapping_add Unexecuted instantiation: <i8 as arbitrary::unstructured::Int>::wrapping_add Unexecuted instantiation: <i16 as arbitrary::unstructured::Int>::wrapping_add Unexecuted instantiation: <i32 as arbitrary::unstructured::Int>::wrapping_add Unexecuted instantiation: <i64 as arbitrary::unstructured::Int>::wrapping_add Unexecuted instantiation: <i128 as arbitrary::unstructured::Int>::wrapping_add Unexecuted instantiation: <isize as arbitrary::unstructured::Int>::wrapping_add |
836 | | |
837 | 15.3k | fn wrapping_sub(self, rhs: Self) -> Self { |
838 | 15.3k | <$ty>::wrapping_sub(self, rhs) |
839 | 15.3k | } <u8 as arbitrary::unstructured::Int>::wrapping_sub Line | Count | Source | 837 | 11.0k | fn wrapping_sub(self, rhs: Self) -> Self { | 838 | 11.0k | <$ty>::wrapping_sub(self, rhs) | 839 | 11.0k | } |
<u16 as arbitrary::unstructured::Int>::wrapping_sub Line | Count | Source | 837 | 3.42k | fn wrapping_sub(self, rhs: Self) -> Self { | 838 | 3.42k | <$ty>::wrapping_sub(self, rhs) | 839 | 3.42k | } |
<u32 as arbitrary::unstructured::Int>::wrapping_sub Line | Count | Source | 837 | 853 | fn wrapping_sub(self, rhs: Self) -> Self { | 838 | 853 | <$ty>::wrapping_sub(self, rhs) | 839 | 853 | } |
Unexecuted instantiation: <u64 as arbitrary::unstructured::Int>::wrapping_sub Unexecuted instantiation: <u128 as arbitrary::unstructured::Int>::wrapping_sub Unexecuted instantiation: <usize as arbitrary::unstructured::Int>::wrapping_sub Unexecuted instantiation: <i8 as arbitrary::unstructured::Int>::wrapping_sub Unexecuted instantiation: <i16 as arbitrary::unstructured::Int>::wrapping_sub Unexecuted instantiation: <i32 as arbitrary::unstructured::Int>::wrapping_sub Unexecuted instantiation: <i64 as arbitrary::unstructured::Int>::wrapping_sub Unexecuted instantiation: <i128 as arbitrary::unstructured::Int>::wrapping_sub Unexecuted instantiation: <isize as arbitrary::unstructured::Int>::wrapping_sub |
840 | | |
841 | 30.6k | fn to_unsigned(self) -> Self::Unsigned { |
842 | 30.6k | self as $unsigned_ty |
843 | 30.6k | } <u8 as arbitrary::unstructured::Int>::to_unsigned Line | Count | Source | 841 | 22.1k | fn to_unsigned(self) -> Self::Unsigned { | 842 | 22.1k | self as $unsigned_ty | 843 | 22.1k | } |
<u16 as arbitrary::unstructured::Int>::to_unsigned Line | Count | Source | 841 | 6.84k | fn to_unsigned(self) -> Self::Unsigned { | 842 | 6.84k | self as $unsigned_ty | 843 | 6.84k | } |
<u32 as arbitrary::unstructured::Int>::to_unsigned Line | Count | Source | 841 | 1.70k | fn to_unsigned(self) -> Self::Unsigned { | 842 | 1.70k | self as $unsigned_ty | 843 | 1.70k | } |
Unexecuted instantiation: <u64 as arbitrary::unstructured::Int>::to_unsigned Unexecuted instantiation: <u128 as arbitrary::unstructured::Int>::to_unsigned Unexecuted instantiation: <usize as arbitrary::unstructured::Int>::to_unsigned Unexecuted instantiation: <i8 as arbitrary::unstructured::Int>::to_unsigned Unexecuted instantiation: <i16 as arbitrary::unstructured::Int>::to_unsigned Unexecuted instantiation: <i32 as arbitrary::unstructured::Int>::to_unsigned Unexecuted instantiation: <i64 as arbitrary::unstructured::Int>::to_unsigned Unexecuted instantiation: <i128 as arbitrary::unstructured::Int>::to_unsigned Unexecuted instantiation: <isize as arbitrary::unstructured::Int>::to_unsigned |
844 | | |
845 | 15.3k | fn from_unsigned(unsigned: $unsigned_ty) -> Self { |
846 | 15.3k | unsigned as Self |
847 | 15.3k | } <u8 as arbitrary::unstructured::Int>::from_unsigned Line | Count | Source | 845 | 11.0k | fn from_unsigned(unsigned: $unsigned_ty) -> Self { | 846 | 11.0k | unsigned as Self | 847 | 11.0k | } |
<u16 as arbitrary::unstructured::Int>::from_unsigned Line | Count | Source | 845 | 3.42k | fn from_unsigned(unsigned: $unsigned_ty) -> Self { | 846 | 3.42k | unsigned as Self | 847 | 3.42k | } |
<u32 as arbitrary::unstructured::Int>::from_unsigned Line | Count | Source | 845 | 853 | fn from_unsigned(unsigned: $unsigned_ty) -> Self { | 846 | 853 | unsigned as Self | 847 | 853 | } |
Unexecuted instantiation: <u64 as arbitrary::unstructured::Int>::from_unsigned Unexecuted instantiation: <u128 as arbitrary::unstructured::Int>::from_unsigned Unexecuted instantiation: <usize as arbitrary::unstructured::Int>::from_unsigned Unexecuted instantiation: <i8 as arbitrary::unstructured::Int>::from_unsigned Unexecuted instantiation: <i16 as arbitrary::unstructured::Int>::from_unsigned Unexecuted instantiation: <i32 as arbitrary::unstructured::Int>::from_unsigned Unexecuted instantiation: <i64 as arbitrary::unstructured::Int>::from_unsigned Unexecuted instantiation: <i128 as arbitrary::unstructured::Int>::from_unsigned Unexecuted instantiation: <isize as arbitrary::unstructured::Int>::from_unsigned |
848 | | } |
849 | | )* |
850 | | } |
851 | | } |
852 | | |
853 | | impl_int! { |
854 | | u8: u8; |
855 | | u16: u16; |
856 | | u32: u32; |
857 | | u64: u64; |
858 | | u128: u128; |
859 | | usize: usize; |
860 | | i8: u8; |
861 | | i16: u16; |
862 | | i32: u32; |
863 | | i64: u64; |
864 | | i128: u128; |
865 | | isize: usize; |
866 | | } |
867 | | |
868 | | #[cfg(test)] |
869 | | mod tests { |
870 | | use super::*; |
871 | | |
872 | | #[test] |
873 | | fn test_byte_size() { |
874 | | let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 6]); |
875 | | // Should take one byte off the end |
876 | | assert_eq!(u.arbitrary_byte_size().unwrap(), 6); |
877 | | assert_eq!(u.len(), 9); |
878 | | let mut v = vec![]; |
879 | | v.resize(260, 0); |
880 | | v.push(1); |
881 | | v.push(4); |
882 | | let mut u = Unstructured::new(&v); |
883 | | // Should read two bytes off the end |
884 | | assert_eq!(u.arbitrary_byte_size().unwrap(), 0x104); |
885 | | assert_eq!(u.len(), 260); |
886 | | } |
887 | | |
888 | | #[test] |
889 | | fn int_in_range_of_one() { |
890 | | let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 6]); |
891 | | let x = u.int_in_range(0..=0).unwrap(); |
892 | | assert_eq!(x, 0); |
893 | | let choice = *u.choose(&[42]).unwrap(); |
894 | | assert_eq!(choice, 42) |
895 | | } |
896 | | |
897 | | #[test] |
898 | | fn int_in_range_uses_minimal_amount_of_bytes() { |
899 | | let mut u = Unstructured::new(&[1, 2]); |
900 | | assert_eq!(1, u.int_in_range::<u8>(0..=u8::MAX).unwrap()); |
901 | | assert_eq!(u.len(), 1); |
902 | | |
903 | | let mut u = Unstructured::new(&[1, 2]); |
904 | | assert_eq!(1, u.int_in_range::<u32>(0..=u8::MAX as u32).unwrap()); |
905 | | assert_eq!(u.len(), 1); |
906 | | |
907 | | let mut u = Unstructured::new(&[1]); |
908 | | assert_eq!(1, u.int_in_range::<u32>(0..=u8::MAX as u32 + 1).unwrap()); |
909 | | assert!(u.is_empty()); |
910 | | } |
911 | | |
912 | | #[test] |
913 | | fn int_in_range_in_bounds() { |
914 | | for input in u8::MIN..=u8::MAX { |
915 | | let input = [input]; |
916 | | |
917 | | let mut u = Unstructured::new(&input); |
918 | | let x = u.int_in_range(1..=u8::MAX).unwrap(); |
919 | | assert_ne!(x, 0); |
920 | | |
921 | | let mut u = Unstructured::new(&input); |
922 | | let x = u.int_in_range(0..=u8::MAX - 1).unwrap(); |
923 | | assert_ne!(x, u8::MAX); |
924 | | } |
925 | | } |
926 | | |
927 | | #[test] |
928 | | fn int_in_range_covers_unsigned_range() { |
929 | | // Test that we generate all values within the range given to |
930 | | // `int_in_range`. |
931 | | |
932 | | let mut full = [false; u8::MAX as usize + 1]; |
933 | | let mut no_zero = [false; u8::MAX as usize]; |
934 | | let mut no_max = [false; u8::MAX as usize]; |
935 | | let mut narrow = [false; 10]; |
936 | | |
937 | | for input in u8::MIN..=u8::MAX { |
938 | | let input = [input]; |
939 | | |
940 | | let mut u = Unstructured::new(&input); |
941 | | let x = u.int_in_range(0..=u8::MAX).unwrap(); |
942 | | full[x as usize] = true; |
943 | | |
944 | | let mut u = Unstructured::new(&input); |
945 | | let x = u.int_in_range(1..=u8::MAX).unwrap(); |
946 | | no_zero[x as usize - 1] = true; |
947 | | |
948 | | let mut u = Unstructured::new(&input); |
949 | | let x = u.int_in_range(0..=u8::MAX - 1).unwrap(); |
950 | | no_max[x as usize] = true; |
951 | | |
952 | | let mut u = Unstructured::new(&input); |
953 | | let x = u.int_in_range(100..=109).unwrap(); |
954 | | narrow[x as usize - 100] = true; |
955 | | } |
956 | | |
957 | | for (i, covered) in full.iter().enumerate() { |
958 | | assert!(covered, "full[{}] should have been generated", i); |
959 | | } |
960 | | for (i, covered) in no_zero.iter().enumerate() { |
961 | | assert!(covered, "no_zero[{}] should have been generated", i); |
962 | | } |
963 | | for (i, covered) in no_max.iter().enumerate() { |
964 | | assert!(covered, "no_max[{}] should have been generated", i); |
965 | | } |
966 | | for (i, covered) in narrow.iter().enumerate() { |
967 | | assert!(covered, "narrow[{}] should have been generated", i); |
968 | | } |
969 | | } |
970 | | |
971 | | #[test] |
972 | | fn int_in_range_covers_signed_range() { |
973 | | // Test that we generate all values within the range given to |
974 | | // `int_in_range`. |
975 | | |
976 | | let mut full = [false; u8::MAX as usize + 1]; |
977 | | let mut no_min = [false; u8::MAX as usize]; |
978 | | let mut no_max = [false; u8::MAX as usize]; |
979 | | let mut narrow = [false; 21]; |
980 | | |
981 | | let abs_i8_min: isize = 128; |
982 | | |
983 | | for input in 0..=u8::MAX { |
984 | | let input = [input]; |
985 | | |
986 | | let mut u = Unstructured::new(&input); |
987 | | let x = u.int_in_range(i8::MIN..=i8::MAX).unwrap(); |
988 | | full[(x as isize + abs_i8_min) as usize] = true; |
989 | | |
990 | | let mut u = Unstructured::new(&input); |
991 | | let x = u.int_in_range(i8::MIN + 1..=i8::MAX).unwrap(); |
992 | | no_min[(x as isize + abs_i8_min - 1) as usize] = true; |
993 | | |
994 | | let mut u = Unstructured::new(&input); |
995 | | let x = u.int_in_range(i8::MIN..=i8::MAX - 1).unwrap(); |
996 | | no_max[(x as isize + abs_i8_min) as usize] = true; |
997 | | |
998 | | let mut u = Unstructured::new(&input); |
999 | | let x = u.int_in_range(-10..=10).unwrap(); |
1000 | | narrow[(x as isize + 10) as usize] = true; |
1001 | | } |
1002 | | |
1003 | | for (i, covered) in full.iter().enumerate() { |
1004 | | assert!(covered, "full[{}] should have been generated", i); |
1005 | | } |
1006 | | for (i, covered) in no_min.iter().enumerate() { |
1007 | | assert!(covered, "no_min[{}] should have been generated", i); |
1008 | | } |
1009 | | for (i, covered) in no_max.iter().enumerate() { |
1010 | | assert!(covered, "no_max[{}] should have been generated", i); |
1011 | | } |
1012 | | for (i, covered) in narrow.iter().enumerate() { |
1013 | | assert!(covered, "narrow[{}] should have been generated", i); |
1014 | | } |
1015 | | } |
1016 | | } |