use std::io; use std::ops::Bound; #[derive(Clone, Debug)] pub struct BoundsRange { pub lower_bound: Bound, pub upper_bound: Bound, } impl BoundsRange { pub fn new(lower_bound: Bound, upper_bound: Bound) -> Self { BoundsRange { lower_bound, upper_bound, } } pub fn is_unbounded(&self) -> bool { matches!(self.lower_bound, Bound::Unbounded) && matches!(self.upper_bound, Bound::Unbounded) } pub fn map_bound(&self, transform: impl Fn(&T) -> TTo) -> BoundsRange { BoundsRange { lower_bound: map_bound(&self.lower_bound, &transform), upper_bound: map_bound(&self.upper_bound, &transform), } } pub fn map_bound_res( &self, transform: impl Fn(&T) -> Result, ) -> Result, Err> { Ok(BoundsRange { lower_bound: map_bound_res(&self.lower_bound, &transform)?, upper_bound: map_bound_res(&self.upper_bound, &transform)?, }) } pub fn transform_inner( &self, transform_lower: impl Fn(&T) -> TransformBound, transform_upper: impl Fn(&T) -> TransformBound, ) -> BoundsRange { BoundsRange { lower_bound: transform_bound_inner(&self.lower_bound, &transform_lower), upper_bound: transform_bound_inner(&self.upper_bound, &transform_upper), } } /// Returns the first set inner value pub fn get_inner(&self) -> Option<&T> { inner_bound(&self.lower_bound).or(inner_bound(&self.upper_bound)) } } pub enum TransformBound { /// Overwrite the bounds NewBound(Bound), /// Use Existing bounds with new value Existing(T), } /// Takes a bound and transforms the inner value into a new bound via a closure. /// The bound variant may change by the value returned value from the closure. pub fn transform_bound_inner_res( bound: &Bound, transform: impl Fn(&TFrom) -> io::Result>, ) -> io::Result> { use self::Bound::*; Ok(match bound { Excluded(from_val) => match transform(from_val)? { TransformBound::NewBound(new_val) => new_val, TransformBound::Existing(new_val) => Excluded(new_val), }, Included(from_val) => match transform(from_val)? { TransformBound::NewBound(new_val) => new_val, TransformBound::Existing(new_val) => Included(new_val), }, Unbounded => Unbounded, }) } /// Takes a bound and transforms the inner value into a new bound via a closure. /// The bound variant may change by the value returned value from the closure. pub fn transform_bound_inner( bound: &Bound, transform: impl Fn(&TFrom) -> TransformBound, ) -> Bound { use self::Bound::*; match bound { Excluded(from_val) => match transform(from_val) { TransformBound::NewBound(new_val) => new_val, TransformBound::Existing(new_val) => Excluded(new_val), }, Included(from_val) => match transform(from_val) { TransformBound::NewBound(new_val) => new_val, TransformBound::Existing(new_val) => Included(new_val), }, Unbounded => Unbounded, } } /// Returns the inner value of a `Bound` pub fn inner_bound(val: &Bound) -> Option<&T> { match val { Bound::Included(term) | Bound::Excluded(term) => Some(term), Bound::Unbounded => None, } } pub fn map_bound( bound: &Bound, transform: impl Fn(&TFrom) -> TTo, ) -> Bound { use self::Bound::*; match bound { Excluded(from_val) => Bound::Excluded(transform(from_val)), Included(from_val) => Bound::Included(transform(from_val)), Unbounded => Unbounded, } } pub fn map_bound_res( bound: &Bound, transform: impl Fn(&TFrom) -> Result, ) -> Result, Err> { use self::Bound::*; Ok(match bound { Excluded(from_val) => Excluded(transform(from_val)?), Included(from_val) => Included(transform(from_val)?), Unbounded => Unbounded, }) }