1use std::fmt::Write;
2
3macro_rules! consume_integral_in_range {
4 ($self:expr, $min:expr, $max:expr, $it:ty) => {{
5 assert!($min <= $max);
6 let range: $it = $max.checked_sub($min).unwrap_or(<$it>::MAX);
7 let mut res: $it = 0;
8 let mut offset: usize = 0;
9
10 let mut bytes_used = 0;
11 let remaining_bytes = $self.remaining_bytes();
12
13 while (offset < std::mem::size_of::<$it>() * u8::BITS as usize)
14 && ((range >> offset) > 0)
15 && (bytes_used != remaining_bytes)
16 {
17 bytes_used += 1;
18 let index = remaining_bytes - bytes_used;
19
20 res = (std::num::Wrapping(res) << u8::BITS as usize).0 | $self.data[index] as $it;
21 offset += u8::BITS as usize;
22 }
23
24 if range as $it != <$it>::MAX {
25 res = res % (range as $it + 1);
26 }
27
28 $self.cursor += bytes_used;
29
30 (std::num::Wrapping($min) + std::num::Wrapping(res)).0
31 }};
32}
33
34macro_rules! consume_probability {
35 ($self:expr, f32) => {
36 $self.consume_u32() as f32 / u32::MAX as f32
37 };
38
39 ($self:expr, f64) => {
40 $self.consume_u64() as f64 / u64::MAX as f64
41 };
42}
43
44macro_rules! consume_floating_point_in_range {
45 ($self:expr, $min:expr, $max:expr, $it:ty) => {{
46 assert!($min < $max);
47 let range: $it;
48 let mut res = $min;
49 let zero: $it = 0.0;
50
51 if $max > zero && $min < zero && $max > $min + <$it>::MAX {
52 range = ($max / 2.0) - ($min / 2.0);
53 if $self.consume_bool() {
54 res += range;
55 }
56 } else {
57 range = $max - $min;
58 }
59
60 res + range
61 }};
62
63 ($self:expr, $min:expr, $max:expr, f32) => {
64 consume_floating_point_in_range!($self, $min, $max, f32) * $self.consume_probability_f32()
65 };
66
67 ($self:expr, $min:expr, $max:expr, f64) => {
68 consume_floating_point_in_range!($self, $min, $max, f64) * $self.consume_probability_f64()
69 };
70}
71
72macro_rules! impl_consume_integral_in_range {
73 ($name:ident, $it:ty) => {
74 #[doc = concat!(
75"Consumes `std::mem::sizeof::<", stringify!($it), ">()` bytes from the provider and returns a value in the range `min..max`\n\n\
76# Arguments:\n\
77\n\
78* `min`: The minimum value in the range\n\
79* `max`: The maximum value in the range\n\
80\n\
81returns: The value between `min..max`")]
82 pub fn $name(&mut self, min: $it, max: $it) -> $it {
83 consume_integral_in_range!(self, min, max, $it)
84 }
85 };
86}
87
88macro_rules! impl_consume_integral {
89 ($name:ident, $it:ty) => {
90 #[doc = concat!(
91"Consumes `std::mem::sizeof::<", stringify!($it), ">()` bytes from the provider an returns value in the range `",
92stringify!($it), "::MIN..", stringify!($it), "::MAX`\n\
93\n\
94returns: The value between `", stringify!($it), "::MIN..", stringify!($it), "::MAX`")]
95 pub fn $name(&mut self) -> $it {
96 consume_integral_in_range!(self, <$it>::MIN, <$it>::MAX, $it)
97 }
98 };
99}
100
101macro_rules! impl_consume_floating_point_in_range {
102 ($name:ident, f32) => {
103 pub fn $name(&mut self, min: f32, max: f32) -> f32 {
112 consume_floating_point_in_range!(self, min, max, f32)
113 }
114 };
115
116 ($name:ident, f64) => {
117 pub fn $name(&mut self, min: f64, max: f64) -> f64 {
126 consume_floating_point_in_range!(self, min, max, f64)
127 }
128 };
129}
130
131macro_rules! impl_consume_floating_point {
132 ($name:ident, f32) => {
133 pub fn $name(&mut self) -> f32 {
137 consume_floating_point_in_range!(self, f32::MIN, f32::MAX, f32)
138 }
139 };
140
141 ($name:ident, f64) => {
142 pub fn $name(&mut self) -> f64 {
146 consume_floating_point_in_range!(self, f64::MIN, f64::MAX, f64)
147 }
148 };
149}
150
151#[derive(Debug)]
152pub struct FuzzedDataProvider<'a> {
153 data: &'a [u8],
154 cursor: usize,
155}
156
157impl<'a> FuzzedDataProvider<'a> {
158 pub fn new(data: &'a [u8]) -> Self {
160 Self { data, cursor: 0 }
161 }
162
163 #[inline]
164 fn has_remaining_bytes(&self) -> bool {
165 self.remaining_bytes() != 0
166 }
167
168 #[inline]
172 pub fn remaining_bytes(&self) -> usize {
173 self.data.len() - self.cursor
174 }
175
176 pub fn consume_bytes(&mut self, num_bytes: usize) -> Vec<u8> {
197 let num_bytes = num_bytes.min(self.remaining_bytes());
198
199 let mut res = Vec::with_capacity(num_bytes);
200 res.extend_from_slice(&self.data[self.cursor..num_bytes]);
201
202 self.cursor += num_bytes;
203
204 res
205 }
206
207 pub fn consume_bytes_as_string(&mut self, num_bytes: usize) -> String {
228 let num_bytes = num_bytes.min(self.remaining_bytes());
229
230 let res = String::from_utf8_lossy(&self.data[self.cursor..num_bytes]).to_string();
231
232 self.cursor += num_bytes;
233
234 res
235 }
236
237 pub fn consume_remaining_bytes(mut self) -> Vec<u8> {
252 self.consume_bytes(self.remaining_bytes())
253 }
254
255 pub fn consume_remaining_bytes_as_string(mut self) -> String {
271 self.consume_bytes_as_string(self.remaining_bytes())
272 }
273
274 pub fn consume_random_length_string(&mut self, max_len: usize) -> String {
297 let mut res = String::with_capacity(max_len.min(self.remaining_bytes()));
298 let mut i = 0usize;
299 while i != max_len && self.has_remaining_bytes() {
300 let mut next = self.data[self.cursor] as char;
301 self.cursor += 1;
302
303 if next == '\\' && self.has_remaining_bytes() {
304 next = self.data[self.cursor] as char;
305 self.cursor += 1;
306
307 if next != '\\' {
308 break;
309 }
310 }
311
312 i += 1;
313
314 if write!(res, "{next}").is_err() {
315 break;
316 }
317 }
318
319 res.shrink_to_fit();
320 res
321 }
322
323 pub fn consume_bool(&mut self) -> bool {
339 (1 & self.consume_u8()) != 0
340 }
341
342 pub fn consume_probability_f32(&mut self) -> f32 {
358 consume_probability!(self, f32)
359 }
360
361 pub fn consume_probability_f64(&mut self) -> f64 {
377 consume_probability!(self, f64)
378 }
379
380 pub fn pick_value_from<T: Clone, S: AsRef<[T]>>(&mut self, slice: S) -> Option<T> {
405 let slice = slice.as_ref();
406 (!slice.is_empty()).then(|| slice[self.consume_usize_in_range(0, slice.len() - 1)].clone())
407 }
408
409 pub fn pick_value_from_or_default<T: Clone + Default, S: AsRef<[T]>>(&mut self, slice: S) -> T {
433 self.pick_value_from(slice).unwrap_or_default()
434 }
435
436 impl_consume_integral_in_range!(consume_i8_in_range, i8);
437 impl_consume_integral_in_range!(consume_u8_in_range, u8);
438 impl_consume_integral_in_range!(consume_i16_in_range, i16);
439 impl_consume_integral_in_range!(consume_u16_in_range, u16);
440 impl_consume_integral_in_range!(consume_i32_in_range, i32);
441 impl_consume_integral_in_range!(consume_u32_in_range, u32);
442 impl_consume_integral_in_range!(consume_i64_in_range, i64);
443 impl_consume_integral_in_range!(consume_u64_in_range, u64);
444 impl_consume_integral_in_range!(consume_i128_in_range, i128);
445 impl_consume_integral_in_range!(consume_u128_in_range, u128);
446 impl_consume_integral_in_range!(consume_usize_in_range, usize);
447 impl_consume_integral_in_range!(consume_isize_in_range, isize);
448
449 impl_consume_integral!(consume_i8, i8);
450 impl_consume_integral!(consume_u8, u8);
451 impl_consume_integral!(consume_i16, i16);
452 impl_consume_integral!(consume_u16, u16);
453 impl_consume_integral!(consume_i32, i32);
454 impl_consume_integral!(consume_u32, u32);
455 impl_consume_integral!(consume_i64, i64);
456 impl_consume_integral!(consume_u64, u64);
457 impl_consume_integral!(consume_i128, i128);
458 impl_consume_integral!(consume_u128, u128);
459 impl_consume_integral!(consume_usize, usize);
460 impl_consume_integral!(consume_isize, isize);
461
462 impl_consume_floating_point_in_range!(consume_f32_in_range, f32);
463 impl_consume_floating_point_in_range!(consume_f64_in_range, f64);
464
465 impl_consume_floating_point!(consume_f32, f32);
466 impl_consume_floating_point!(consume_f64, f64);
467}
468
469#[cfg(test)]
470mod tests {
471 use crate::FuzzedDataProvider;
472
473 #[test]
474 fn test_consume_empty_returns_empty_vec() {
475 let fp = FuzzedDataProvider::new(&[]);
476 assert_eq!(fp.consume_remaining_bytes(), vec![]);
477 }
478
479 #[test]
480 fn test_consume_empty_as_string_returns_empty_string() {
481 let fp = FuzzedDataProvider::new(&[]);
482 assert_eq!(fp.consume_remaining_bytes_as_string(), String::new());
483 }
484
485 #[test]
486 fn test_consume_remaining_as_string() {
487 let fp = FuzzedDataProvider::new(&[b'@', b'A', b'B']);
488 assert_eq!(fp.consume_remaining_bytes_as_string(), "@AB");
489 }
490
491 #[test]
492 fn test_consume_bytes() {
493 let mut fp = FuzzedDataProvider::new(&[1, 2, 3]);
494 assert_eq!(fp.consume_bytes(2), vec![1, 2]);
495 }
496
497 #[test]
498 fn test_consume_probability_f32() {
499 let mut fp = FuzzedDataProvider::new(&[255, 0]);
500 assert!((0.0f32..1.0f32).contains(&fp.consume_probability_f32()));
501 }
502
503 #[test]
504 fn test_consume_probability_f64() {
505 let mut fp = FuzzedDataProvider::new(&[1, 200, 10, 20]);
506 assert!((0.0f64..1.0f64).contains(&fp.consume_probability_f64()));
507 }
508
509 #[test]
510 fn test_consume_integral_u8() {
511 let mut fp = FuzzedDataProvider::new(&[255, 1]);
512 assert_eq!(fp.consume_u8(), 1);
513 assert_eq!(fp.consume_u8(), 255);
514 }
515
516 #[test]
517 fn test_consume_integral_i8() {
518 let mut fp = FuzzedDataProvider::new(&[255, 1]);
519 assert_eq!(fp.consume_i8(), -127);
520 assert_eq!(fp.consume_i8(), 127);
521 }
522
523 #[test]
524 fn test_consume_integral_u16() {
525 let mut fp = FuzzedDataProvider::new(&[1, 1]);
526 assert_eq!(fp.consume_u16(), 257);
527 }
528
529 #[test]
530 fn test_consume_integral_i16() {
531 let mut fp = FuzzedDataProvider::new(&[1, 1]);
532 assert_eq!(fp.consume_i16(), -32511);
533 }
534
535 #[test]
536 fn test_consume_integral_u32_without_sufficient_bytes() {
537 let mut fp = FuzzedDataProvider::new(&[1, 1]);
538 assert_eq!(fp.consume_u32(), 257);
539 }
540
541 #[test]
542 fn test_consume_integral_in_range_u8() {
543 let mut fp = FuzzedDataProvider::new(&[255]);
544 assert_eq!(fp.consume_u8_in_range(1, 10), 6);
545 }
546
547 #[test]
548 fn test_consume_bool() {
549 let mut fp = FuzzedDataProvider::new(&[0, 1, 11]);
550 assert_eq!(fp.consume_bool(), true);
551 assert_eq!(fp.consume_bool(), true);
552 assert_eq!(fp.consume_bool(), false);
553 }
554
555 #[test]
556 fn test_consume_floating_point_f32() {
557 let mut fp = FuzzedDataProvider::new(&[1, 2, 3, 4, 5]);
558 assert_eq!(fp.consume_f32(), 3.4028235e38);
559 }
560
561 #[test]
562 fn test_consume_floating_point_f64() {
563 let mut fp = FuzzedDataProvider::new(&[1, 2, 3, 4, 5, 6, 7, 8, 11]);
564 assert_eq!(fp.consume_f64(), 1.7976931348623157e308);
565 }
566
567 #[test]
568 fn test_consume_floating_point_in_range_f32() {
569 let mut fp = FuzzedDataProvider::new(&[1, 2, 3, 4, 5]);
570 assert_eq!(fp.consume_f32_in_range(1.0, 1.5), 1.5);
571 }
572
573 #[test]
574 fn test_consume_floating_point_in_range_f64() {
575 let mut fp = FuzzedDataProvider::new(&[1, 2, 3, 4, 5, 6, 7, 8, 11]);
576 assert_eq!(fp.consume_f64_in_range(1.1, 1.9), 1.9);
577 }
578
579 #[test]
580 fn test_pick_value_from() {
581 let values = [1, 2, 3, 4, 5];
582 let mut fp = FuzzedDataProvider::new(&[0, 1, 2, 3]);
583 assert_eq!(fp.pick_value_from(&values), Some(4));
584 assert_eq!(fp.pick_value_from(&values), Some(3));
585 }
586
587 #[test]
588 fn test_consume_random_length_string() {
589 let mut fp = FuzzedDataProvider::new(&[b'@', b'1', b'5', b'\\', b'7', b'8', b'9']);
590 assert_eq!(fp.consume_random_length_string(10), "@15");
591 assert_eq!(fp.consume_random_length_string(10), "89");
592 }
593
594 #[test]
595 fn test_consume_integral_from_empty_provider() {
596 let mut fp = FuzzedDataProvider::new(&[]);
597 assert_eq!(fp.consume_u32(), 0);
598 }
599
600 #[test]
601 fn test_consume_floating_point_from_empty_provider() {
602 let mut fp = FuzzedDataProvider::new(&[]);
603 assert_eq!(fp.consume_f64(), 0.0);
604 }
605}