Skip to main content

ranch/
quotient.rs

1/// The result of a division
2#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
3pub enum Quotient<T>
4where
5    T: Copy + Clone,
6{
7    /// Result from division by 0
8    Nan,
9    /// Numeric value of the quotient
10    Number(T),
11}
12
13impl<T> Quotient<T>
14where
15    T: Copy + Clone,
16{
17    /// Map a `Quotient<T>` to `Quotient<U>` by applying a function to a
18    /// contained value.
19    pub fn map<U, F>(self, f: F) -> Quotient<U>
20    where
21        F: FnOnce(T) -> U,
22        U: Copy + Clone,
23    {
24        match self {
25            Self::Nan => Quotient::Nan,
26            Self::Number(n) => Quotient::Number(f(n)),
27        }
28    }
29
30    /// Convert from `Quotient<T>` to `Option<T>`.
31    pub const fn number(self) -> Option<T> {
32        let Self::Number(number) = self else {
33            return None;
34        };
35
36        Some(number)
37    }
38
39    /// Convert from `&mut Quotient<T>` to `Option<&mut T>`.
40    pub const fn number_mut(&mut self) -> Option<&mut T> {
41        let Self::Number(number) = self else {
42            return None;
43        };
44
45        Some(number)
46    }
47
48    /// Return true if the quotient is a [`Number`](Self::Number) value.
49    pub const fn is_number(self) -> bool {
50        matches!(self, Self::Number(_))
51    }
52
53    /// Return true if the quotient is a [`Nan`](Self::Nan) value.
54    pub const fn is_nan(self) -> bool {
55        matches!(self, Self::Nan)
56    }
57
58    /// Transform the `Quotient<T>` into a [`Result<T, E>`], mapping `Number(v)`
59    /// to `Ok(v)` and `Nan` to `Err(err)`.
60    pub fn ok_or<E>(self, err: E) -> Result<T, E> {
61        self.number().ok_or(err)
62    }
63
64    /// Transform the `Quotient<T>` into a [`Result<T, E>`], mapping `Number(v)`
65    /// to `Ok(v)` and `Nan` to `Err(err)`.
66    pub fn ok_or_else<E, F>(self, f: F) -> Result<T, E>
67    where
68        F: FnOnce() -> E,
69    {
70        self.number().ok_or_else(f)
71    }
72
73    /// Return the number if not [`Nan`](Self::Nan), otherwise returns `other`.
74    pub fn or(self, other: Self) -> Self {
75        let Some(result) = self.number().or(other.number()) else {
76            return Quotient::Nan;
77        };
78
79        Quotient::Number(result)
80    }
81
82    /// Return the number if not [`Nan`](Self::Nan), otherwise call `f` and
83    /// return the result.
84    pub fn or_else<F>(self, f: F) -> Self
85    where
86        F: FnOnce() -> Self,
87    {
88        let Some(number) = self.number().or_else(|| f().number()) else {
89            return Quotient::Nan;
90        };
91
92        Quotient::Number(number)
93    }
94
95    /// Return [`Nan`](Self::Nan) if `self` is [`Nan`](Self::Nan), otherwise
96    /// return `other`.
97    pub fn and<U>(self, other: Quotient<U>) -> Quotient<U>
98    where
99        U: Copy + Clone,
100    {
101        let Some(result) = self.number().and(other.number()) else {
102            return Quotient::Nan;
103        };
104
105        Quotient::Number(result)
106    }
107
108    /// Return [`Nan`](Self::Nan) if `self` is [`Nan`](Self::Nan), otherwise
109    /// call `f` with the number and return the result.
110    pub fn and_then<U, F>(self, f: F) -> Quotient<U>
111    where
112        F: FnOnce(T) -> Quotient<U>,
113        U: Copy + Clone,
114    {
115        let Some(number) = self.number().and_then(|n| f(n).number()) else {
116            return Quotient::Nan;
117        };
118
119        Quotient::Number(number)
120    }
121
122    /// Return [`Number`](Self::Number) if exactly one of `self` and `other` are
123    /// [`Number`](Self::Number), otherwise return [`Nan`](Self::Nan).
124    pub fn xor(self, other: Self) -> Self {
125        let Some(result) = self.number().xor(other.number()) else {
126            return Quotient::Nan;
127        };
128
129        Quotient::Number(result)
130    }
131}