mod count;
pub use count::{Count, Countable};
mod width;
pub use width::Width;
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
pub enum Measurement<T> {
Finite(T),
Infinite,
}
impl<T> Measurement<T> {
pub fn is_infinite(&self) -> bool {
matches!(self, Self::Infinite)
}
pub fn is_finite(&self) -> bool {
matches!(self, Self::Finite(_))
}
pub fn expect_finite(self, msg: &str) -> T {
match self {
Self::Finite(inner) => inner,
_ => panic!("{}", msg),
}
}
pub fn finite(self) -> T {
self.expect_finite("Measurement should be finite")
}
pub fn finite_or(self, default: T) -> T {
match self {
Self::Finite(inner) => inner,
_ => default,
}
}
pub fn flat_map<U>(self, func: impl FnOnce(T) -> Measurement<U>) -> Measurement<U> {
match self {
Self::Finite(inner) => func(inner),
Self::Infinite => Measurement::<U>::Infinite,
}
}
pub fn map<U>(self, func: impl FnOnce(T) -> U) -> Measurement<U> {
match self {
Self::Finite(inner) => Measurement::Finite(func(inner)),
Self::Infinite => Measurement::<U>::Infinite,
}
}
fn binop_map(self, rhs: Self, func: impl Fn(T, T) -> T) -> Self {
let lhs = match self {
Self::Finite(inner) => inner,
Self::Infinite => return Self::Infinite,
};
let rhs = match rhs {
Self::Finite(inner) => inner,
Self::Infinite => return Self::Infinite,
};
Self::Finite(func(lhs, rhs))
}
#[allow(dead_code)]
fn binop_try_map(self, rhs: Self, func: impl Fn(&T, &T) -> Option<T>) -> Self {
let lhs = match self {
Self::Finite(inner) => inner,
Self::Infinite => return Self::Infinite,
};
let rhs = match rhs {
Self::Finite(inner) => inner,
Self::Infinite => return Self::Infinite,
};
func(&lhs, &rhs)
.map(|v| Self::Finite(v))
.unwrap_or(Self::Infinite)
}
}
impl<T> core::ops::Add for Measurement<T>
where
T: Clone + core::ops::Add<T, Output = T>,
{
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
self.binop_map(rhs, T::add)
}
}
impl<T> core::ops::Sub for Measurement<T>
where
T: Clone + core::ops::Sub<T, Output = T>,
{
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
self.binop_map(rhs, T::sub)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_measurement_ord() {
assert_eq!(Measurement::Finite(10) < Measurement::Infinite, true,);
}
}