use std::ops::{Bound, RangeBounds};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct RangeCfg {
start: Bound<usize>,
end: Bound<usize>,
}
impl RangeCfg {
pub fn contains(&self, value: &usize) -> bool {
match &self.start {
Bound::Included(s) if value < s => return false,
Bound::Excluded(s) if value <= s => return false,
_ => {}
}
match &self.end {
Bound::Included(e) if value > e => return false,
Bound::Excluded(e) if value >= e => return false,
_ => {}
}
true
}
}
impl<R: RangeBounds<usize>> From<R> for RangeCfg {
fn from(r: R) -> Self {
fn own(b: Bound<&usize>) -> Bound<usize> {
match b {
Bound::Included(&v) => Bound::Included(v),
Bound::Excluded(&v) => Bound::Excluded(v),
Bound::Unbounded => Bound::Unbounded,
}
}
RangeCfg {
start: own(r.start_bound()),
end: own(r.end_bound()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::ops::Bound::{Excluded, Included, Unbounded};
#[test]
fn test_range_cfg_from() {
let cfg_full: RangeCfg = (..).into();
assert_eq!(
cfg_full,
RangeCfg {
start: Unbounded,
end: Unbounded
}
);
let cfg_start_incl: RangeCfg = (5..).into();
assert_eq!(
cfg_start_incl,
RangeCfg {
start: Included(5),
end: Unbounded
}
);
let cfg_end_excl: RangeCfg = (..10).into();
assert_eq!(
cfg_end_excl,
RangeCfg {
start: Unbounded,
end: Excluded(10)
}
);
let cfg_end_incl: RangeCfg = (..=10).into();
assert_eq!(
cfg_end_incl,
RangeCfg {
start: Unbounded,
end: Included(10)
}
);
let cfg_incl_excl: RangeCfg = (5..10).into();
assert_eq!(
cfg_incl_excl,
RangeCfg {
start: Included(5),
end: Excluded(10)
}
);
let cfg_incl_incl: RangeCfg = (5..=10).into();
assert_eq!(
cfg_incl_incl,
RangeCfg {
start: Included(5),
end: Included(10)
}
);
struct ExclusiveStartRange(usize, usize);
impl RangeBounds<usize> for ExclusiveStartRange {
fn start_bound(&self) -> Bound<&usize> {
Excluded(&self.0)
}
fn end_bound(&self) -> Bound<&usize> {
Included(&self.1)
}
}
let cfg_excl_incl: RangeCfg = ExclusiveStartRange(5, 10).into();
assert_eq!(
cfg_excl_incl,
RangeCfg {
start: Excluded(5),
end: Included(10)
}
);
}
#[test]
fn test_range_cfg_contains() {
let cfg_unbounded: RangeCfg = (..).into();
assert!(cfg_unbounded.contains(&0));
assert!(cfg_unbounded.contains(&100));
assert!(cfg_unbounded.contains(&usize::MAX));
let cfg_start_incl: RangeCfg = (5..).into();
assert!(!cfg_start_incl.contains(&4));
assert!(cfg_start_incl.contains(&5));
assert!(cfg_start_incl.contains(&6));
assert!(cfg_start_incl.contains(&usize::MAX));
let cfg_end_excl: RangeCfg = (..10).into();
assert!(cfg_end_excl.contains(&0));
assert!(cfg_end_excl.contains(&9));
assert!(!cfg_end_excl.contains(&10));
assert!(!cfg_end_excl.contains(&11));
let cfg_end_incl: RangeCfg = (..=10).into();
assert!(cfg_end_incl.contains(&0));
assert!(cfg_end_incl.contains(&9));
assert!(cfg_end_incl.contains(&10));
assert!(!cfg_end_incl.contains(&11));
let cfg_incl_excl: RangeCfg = (5..10).into();
assert!(!cfg_incl_excl.contains(&4));
assert!(cfg_incl_excl.contains(&5));
assert!(cfg_incl_excl.contains(&9));
assert!(!cfg_incl_excl.contains(&10));
assert!(!cfg_incl_excl.contains(&11));
let cfg_incl_incl: RangeCfg = (5..=10).into();
assert!(!cfg_incl_incl.contains(&4));
assert!(cfg_incl_incl.contains(&5));
assert!(cfg_incl_incl.contains(&9));
assert!(cfg_incl_incl.contains(&10));
assert!(!cfg_incl_incl.contains(&11));
let cfg_excl_incl = RangeCfg {
start: Excluded(5),
end: Included(10),
};
assert!(!cfg_excl_incl.contains(&4));
assert!(!cfg_excl_incl.contains(&5)); assert!(cfg_excl_incl.contains(&6));
assert!(cfg_excl_incl.contains(&10)); assert!(!cfg_excl_incl.contains(&11));
let cfg_excl_excl = RangeCfg {
start: Excluded(5),
end: Excluded(10),
};
assert!(!cfg_excl_excl.contains(&5)); assert!(cfg_excl_excl.contains(&6));
assert!(cfg_excl_excl.contains(&9));
assert!(!cfg_excl_excl.contains(&10)); }
#[test]
fn test_contains_empty_range() {
let cfg_empty_excl: RangeCfg = (5..5).into();
assert!(!cfg_empty_excl.contains(&4));
assert!(!cfg_empty_excl.contains(&5));
assert!(!cfg_empty_excl.contains(&6));
#[allow(clippy::reversed_empty_ranges)]
let cfg_empty_incl: RangeCfg = (6..=5).into();
assert!(!cfg_empty_incl.contains(&5));
assert!(!cfg_empty_incl.contains(&6));
}
}