1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use super::StreamId;
#[cfg(any(test, feature = "generator"))]
use bolero_generator::prelude::*;
/// An Iterator over Stream Ids of a particular type.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(any(feature = "generator", test), derive(TypeGenerator))]
pub struct StreamIter {
start_stream_id: StreamId,
max_stream_id: StreamId,
finished: bool,
}
impl StreamIter {
#[inline]
pub fn new(start_stream_id: StreamId, max_stream_id: StreamId) -> Self {
debug_assert_eq!(start_stream_id.stream_type(), max_stream_id.stream_type());
debug_assert_eq!(start_stream_id.initiator(), max_stream_id.initiator());
debug_assert!(start_stream_id <= max_stream_id);
Self {
start_stream_id,
max_stream_id,
finished: false,
}
}
#[inline]
pub fn max_stream_id(self) -> StreamId {
self.max_stream_id
}
}
impl Iterator for StreamIter {
type Item = StreamId;
fn next(&mut self) -> Option<Self::Item> {
// short circuit when finished
if self.finished {
return None;
}
match self.start_stream_id.cmp(&self.max_stream_id) {
core::cmp::Ordering::Less => {
let ret = self.start_stream_id;
// The Stream ID can be expected to be valid, since `max_stream_id`
// is a valid `StreamId` and all IDs we iterate over are lower.
self.start_stream_id = self
.start_stream_id
.next_of_type()
.expect("Expect a valid Stream ID");
Some(ret)
}
core::cmp::Ordering::Equal => {
// Avoid incrementing beyond `max_stream_id` and mark finished to
// to avoid returning max value again
self.finished = true;
Some(self.start_stream_id)
}
core::cmp::Ordering::Greater => {
debug_assert!(false, "The `new` method should verify valid ranges");
// finished
self.finished = true;
None
}
}
}
}
#[cfg(test)]
mod fuzz_target {
use super::*;
#[test]
#[cfg_attr(miri, ignore)] // This test is too expensive for miri to complete in a reasonable amount of time
#[cfg_attr(kani, kani::proof, kani::unwind(1), kani::solver(kissat))]
fn fuzz_builder() {
bolero::check!()
.with_type::<(StreamId, StreamId)>()
.cloned()
.for_each(|(min, max)| {
// enforce min <= max
if min > max {
return;
}
// enforce same initiator type
if min.initiator() != max.initiator() {
return;
}
// enforce same stream type
if min.stream_type() != max.stream_type() {
return;
}
// All other combinations of min/max StreamId should be valid
StreamIter::new(min, max);
});
}
}