1#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
3pub enum Quotient<T>
4where
5 T: Copy + Clone,
6{
7 Nan,
9 Number(T),
11}
12
13impl<T> Quotient<T>
14where
15 T: Copy + Clone,
16{
17 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 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 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 pub const fn is_number(self) -> bool {
50 matches!(self, Self::Number(_))
51 }
52
53 pub const fn is_nan(self) -> bool {
55 matches!(self, Self::Nan)
56 }
57
58 pub fn ok_or<E>(self, err: E) -> Result<T, E> {
61 self.number().ok_or(err)
62 }
63
64 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 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 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 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 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 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}