use crate::raw_interval::RawInterval;
pub trait Finite: Sized {
const MINIMUM: Self;
const MAXIMUM: Self;
fn pred(&self) -> Option<Self>;
fn succ(&self) -> Option<Self>;
}
pub trait Normalize {
fn normalize(&mut self);
fn denormalize(&mut self);
#[must_use]
fn normalized(mut self) -> Self where Self: Sized {
self.normalize();
self
}
#[must_use]
fn denormalized(mut self) -> Self where Self: Sized {
self.denormalize();
self
}
}
impl<T> Normalize for RawInterval<T> where T: Finite {
fn normalize(&mut self) {
use RawInterval::*;
*self = match std::mem::replace(self, Empty) {
Empty => Empty,
Point(p) => Point(p),
Open(l, r) => match (l.succ(), r.pred()) {
(Some(l), Some(r)) => Closed(l, r),
_ => Empty,
},
LeftOpen(l, r) => l.succ().map_or(Empty, |l| Closed(l, r)),
RightOpen(l, r) => r.pred().map_or(Empty, |r| Closed(l, r)),
Closed(l, r) => Closed(l, r),
UpTo(r) => r.pred().map_or(Empty, |r| Closed(T::MINIMUM, r)),
UpFrom(l) => l.succ().map_or(Empty, |l| Closed(l, T::MAXIMUM)),
To(p) => Closed(T::MINIMUM, p),
From(p) => Closed(p, T::MAXIMUM),
Full => Closed(T::MINIMUM, T::MAXIMUM),
}
}
fn denormalize(&mut self) {
use RawInterval::*;
*self = match std::mem::replace(self, Empty) {
Empty => Empty,
Point(p) => match (p.pred(), p.succ()) {
(Some(l), Some(r)) => Open(l, r),
(Some(l), None) => UpFrom(l),
(None, Some(r)) => UpTo(r),
_ => Full,
},
Open(l, r) => Open(l, r),
LeftOpen(l, r) => match r.succ() {
Some(r) => Open(l, r),
None => UpFrom(l),
},
RightOpen(l, r) => match l.pred() {
Some(l) => Open(l, r),
None => UpTo(r),
},
Closed(l, r) => match (l.pred(), r.succ()) {
(Some(l), Some(r)) => Open(l, r),
(Some(l), None) => UpFrom(l),
(None, Some(r)) => UpTo(r),
_ => Full,
},
UpTo(r) => UpTo(r),
UpFrom(l) => UpFrom(l),
To(p) => p.pred().map_or(Empty, |r| UpTo(r)),
From(p) => p.succ().map_or(Empty, |l| UpFrom(l)),
Full => Full,
}
}
}
macro_rules! std_integer_countable_impl {
($($t:ident),*) => {
$(impl Finite for $t {
const MINIMUM: $t = {$t::MIN};
const MAXIMUM: $t = {$t::MAX};
fn pred(&self) -> Option<Self> {
(*self != $t::MIN).then(|| self - 1)
}
fn succ(&self) -> Option<Self> {
(*self != $t::MAX).then(|| self + 1)
}
})*
};
}
std_integer_countable_impl![
u8, u16, u32, u64, u128, usize,
i8, i16, i32, i64, i128, isize
];