s2n_codec/decoder/
checked_range.rs1use core::fmt;
5
6#[derive(Copy, Clone)]
7pub struct CheckedRange {
8 start: usize,
9 end: usize,
10
11 #[cfg(all(debug_assertions, feature = "checked_range_unsafe"))]
12 original_ptr: *const u8,
13}
14
15#[cfg(test)]
16impl bolero::TypeGenerator for CheckedRange {
17 fn generate<D: bolero::Driver>(driver: &mut D) -> Option<Self> {
18 use bolero::ValueGenerator;
19
20 let start = bolero::produce::<usize>().generate(driver)?;
21 let end = (start..).generate(driver)?;
22 Some(CheckedRange::new(start, end, core::ptr::null()))
23 }
24}
25
26impl CheckedRange {
27 #[inline]
28 pub(crate) fn new(start: usize, end: usize, original_ptr: *const u8) -> Self {
29 debug_assert!(
30 end >= start,
31 "end: {end} must be greater than or equal to start: {start}",
32 );
33 #[cfg(not(all(debug_assertions, feature = "checked_range_unsafe")))]
34 let _ = original_ptr;
35
36 Self {
37 start,
38 end,
39 #[cfg(all(debug_assertions, feature = "checked_range_unsafe"))]
40 original_ptr,
41 }
42 }
43
44 #[cfg(feature = "checked_range_unsafe")]
45 #[inline]
46 pub fn get<'a>(&self, slice: &'a [u8]) -> &'a [u8] {
47 unsafe {
48 #[cfg(debug_assertions)]
49 debug_assert_eq!(slice.as_ptr().add(self.start), self.original_ptr);
50
51 slice.get_unchecked(self.start..self.end)
52 }
53 }
54
55 #[cfg(not(feature = "checked_range_unsafe"))]
56 #[inline]
57 pub fn get<'a>(&self, slice: &'a [u8]) -> &'a [u8] {
58 &slice[self.start..self.end]
59 }
60
61 #[cfg(feature = "checked_range_unsafe")]
62 #[inline]
63 pub fn get_mut<'a>(&self, slice: &'a mut [u8]) -> &'a mut [u8] {
64 unsafe {
65 #[cfg(debug_assertions)]
66 debug_assert_eq!(slice.as_ptr().add(self.start), self.original_ptr);
67
68 slice.get_unchecked_mut(self.start..self.end)
69 }
70 }
71
72 #[cfg(not(feature = "checked_range_unsafe"))]
73 #[inline]
74 pub fn get_mut<'a>(&self, slice: &'a mut [u8]) -> &'a mut [u8] {
75 &mut slice[self.start..self.end]
76 }
77
78 #[inline]
79 pub fn len(&self) -> usize {
80 self.end - self.start
81 }
82
83 #[inline]
84 pub fn is_empty(&self) -> bool {
85 self.start == self.end
86 }
87}
88
89impl fmt::Debug for CheckedRange {
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91 write!(f, "{}..{}", self.start, self.end)
92 }
93}
94
95#[cfg(test)]
96mod tests {
97
98 use super::*;
99
100 #[test]
101 #[cfg_attr(kani, kani::proof)]
102 fn checked_range_len() {
103 bolero::check!()
104 .with_type()
105 .for_each(|callee: &CheckedRange| Some(callee.len()));
106 }
107
108 #[test]
109 #[cfg_attr(kani, kani::proof)]
110 fn checked_range_is_empty() {
111 bolero::check!()
112 .with_type()
113 .for_each(|callee: &CheckedRange| Some(callee.is_empty()));
114 }
115}