commonware_codec/
config.rs1use core::ops::{Bound, RangeBounds};
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
25pub struct RangeCfg {
26 start: Bound<usize>,
28
29 end: Bound<usize>,
31}
32
33impl RangeCfg {
34 pub fn contains(&self, value: &usize) -> bool {
36 match &self.start {
38 Bound::Included(s) if value < s => return false,
39 Bound::Excluded(s) if value <= s => return false,
40 _ => {}
41 }
42
43 match &self.end {
45 Bound::Included(e) if value > e => return false,
46 Bound::Excluded(e) if value >= e => return false,
47 _ => {}
48 }
49
50 true
52 }
53}
54
55impl<R: RangeBounds<usize>> From<R> for RangeCfg {
57 fn from(r: R) -> Self {
58 fn own(b: Bound<&usize>) -> Bound<usize> {
59 match b {
60 Bound::Included(&v) => Bound::Included(v),
61 Bound::Excluded(&v) => Bound::Excluded(v),
62 Bound::Unbounded => Bound::Unbounded,
63 }
64 }
65
66 RangeCfg {
67 start: own(r.start_bound()),
68 end: own(r.end_bound()),
69 }
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use core::ops::Bound::{Excluded, Included, Unbounded};
77
78 #[test]
79 fn test_range_cfg_from() {
80 let cfg_full: RangeCfg = (..).into();
82 assert_eq!(
83 cfg_full,
84 RangeCfg {
85 start: Unbounded,
86 end: Unbounded
87 }
88 );
89
90 let cfg_start_incl: RangeCfg = (5..).into();
92 assert_eq!(
93 cfg_start_incl,
94 RangeCfg {
95 start: Included(5),
96 end: Unbounded
97 }
98 );
99
100 let cfg_end_excl: RangeCfg = (..10).into();
102 assert_eq!(
103 cfg_end_excl,
104 RangeCfg {
105 start: Unbounded,
106 end: Excluded(10)
107 }
108 );
109
110 let cfg_end_incl: RangeCfg = (..=10).into();
112 assert_eq!(
113 cfg_end_incl,
114 RangeCfg {
115 start: Unbounded,
116 end: Included(10)
117 }
118 );
119
120 let cfg_incl_excl: RangeCfg = (5..10).into();
122 assert_eq!(
123 cfg_incl_excl,
124 RangeCfg {
125 start: Included(5),
126 end: Excluded(10)
127 }
128 );
129
130 let cfg_incl_incl: RangeCfg = (5..=10).into();
132 assert_eq!(
133 cfg_incl_incl,
134 RangeCfg {
135 start: Included(5),
136 end: Included(10)
137 }
138 );
139
140 struct ExclusiveStartRange(usize, usize);
142 impl RangeBounds<usize> for ExclusiveStartRange {
143 fn start_bound(&self) -> Bound<&usize> {
144 Excluded(&self.0)
145 }
146 fn end_bound(&self) -> Bound<&usize> {
147 Included(&self.1)
148 }
149 }
150 let cfg_excl_incl: RangeCfg = ExclusiveStartRange(5, 10).into();
151 assert_eq!(
152 cfg_excl_incl,
153 RangeCfg {
154 start: Excluded(5),
155 end: Included(10)
156 }
157 );
158 }
159
160 #[test]
161 fn test_range_cfg_contains() {
162 let cfg_unbounded: RangeCfg = (..).into();
164 assert!(cfg_unbounded.contains(&0));
165 assert!(cfg_unbounded.contains(&100));
166 assert!(cfg_unbounded.contains(&usize::MAX));
167
168 let cfg_start_incl: RangeCfg = (5..).into();
170 assert!(!cfg_start_incl.contains(&4));
171 assert!(cfg_start_incl.contains(&5));
172 assert!(cfg_start_incl.contains(&6));
173 assert!(cfg_start_incl.contains(&usize::MAX));
174
175 let cfg_end_excl: RangeCfg = (..10).into();
177 assert!(cfg_end_excl.contains(&0));
178 assert!(cfg_end_excl.contains(&9));
179 assert!(!cfg_end_excl.contains(&10));
180 assert!(!cfg_end_excl.contains(&11));
181
182 let cfg_end_incl: RangeCfg = (..=10).into();
184 assert!(cfg_end_incl.contains(&0));
185 assert!(cfg_end_incl.contains(&9));
186 assert!(cfg_end_incl.contains(&10));
187 assert!(!cfg_end_incl.contains(&11));
188
189 let cfg_incl_excl: RangeCfg = (5..10).into();
191 assert!(!cfg_incl_excl.contains(&4));
192 assert!(cfg_incl_excl.contains(&5));
193 assert!(cfg_incl_excl.contains(&9));
194 assert!(!cfg_incl_excl.contains(&10));
195 assert!(!cfg_incl_excl.contains(&11));
196
197 let cfg_incl_incl: RangeCfg = (5..=10).into();
199 assert!(!cfg_incl_incl.contains(&4));
200 assert!(cfg_incl_incl.contains(&5));
201 assert!(cfg_incl_incl.contains(&9));
202 assert!(cfg_incl_incl.contains(&10));
203 assert!(!cfg_incl_incl.contains(&11));
204
205 let cfg_excl_incl = RangeCfg {
207 start: Excluded(5),
208 end: Included(10),
209 };
210 assert!(!cfg_excl_incl.contains(&4));
211 assert!(!cfg_excl_incl.contains(&5)); assert!(cfg_excl_incl.contains(&6));
213 assert!(cfg_excl_incl.contains(&10)); assert!(!cfg_excl_incl.contains(&11));
215
216 let cfg_excl_excl = RangeCfg {
218 start: Excluded(5),
219 end: Excluded(10),
220 };
221 assert!(!cfg_excl_excl.contains(&5)); assert!(cfg_excl_excl.contains(&6));
223 assert!(cfg_excl_excl.contains(&9));
224 assert!(!cfg_excl_excl.contains(&10)); }
226
227 #[test]
228 fn test_contains_empty_range() {
229 let cfg_empty_excl: RangeCfg = (5..5).into();
231 assert!(!cfg_empty_excl.contains(&4));
232 assert!(!cfg_empty_excl.contains(&5));
233 assert!(!cfg_empty_excl.contains(&6));
234
235 #[allow(clippy::reversed_empty_ranges)]
237 let cfg_empty_incl: RangeCfg = (6..=5).into();
238 assert!(!cfg_empty_incl.contains(&5));
239 assert!(!cfg_empty_incl.contains(&6));
240 }
241}