1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Approximation<T, E> {
6 Exact(T),
8
9 Inexact(T, E),
11}
12
13impl<T, E> Approximation<T, E> {
14 #[inline]
16 pub fn value(self) -> T {
17 match self {
18 Self::Exact(v) => v,
19 Self::Inexact(v, _) => v,
20 }
21 }
22
23 #[inline]
25 pub const fn value_ref(&self) -> &T {
26 match self {
27 Self::Exact(v) => v,
28 Self::Inexact(v, _) => v,
29 }
30 }
31
32 #[inline]
39 pub fn value_with_exact(self) -> (T, bool) {
40 match self {
41 Self::Exact(v) => (v, true),
42 Self::Inexact(v, _) => (v, false),
43 }
44 }
45
46 #[inline]
48 pub fn unwrap(self) -> T {
49 match self {
50 Self::Exact(val) => val,
51 Self::Inexact(_, _) => panic!("called `Approximation::unwrap()` on a `Inexact` value"),
52 }
53 }
54
55 #[inline]
57 pub fn error(self) -> Option<E> {
58 match self {
59 Self::Exact(_) => None,
60 Self::Inexact(_, e) => Some(e),
61 }
62 }
63
64 #[inline]
66 pub const fn error_ref(&self) -> Option<&E> {
67 match self {
68 Self::Exact(_) => None,
69 Self::Inexact(_, e) => Some(e),
70 }
71 }
72
73 #[inline]
75 pub fn map<U, F>(self, f: F) -> Approximation<U, E>
76 where
77 F: FnOnce(T) -> U,
78 {
79 match self {
80 Self::Exact(v) => Approximation::Exact(f(v)),
81 Self::Inexact(v, e) => Approximation::Inexact(f(v), e),
82 }
83 }
84
85 #[inline]
88 pub fn and_then<U, F>(self, f: F) -> Approximation<U, E>
89 where
90 F: FnOnce(T) -> Approximation<U, E>,
91 {
92 match self {
93 Self::Exact(v) => match f(v) {
94 Approximation::Exact(v2) => Approximation::Exact(v2),
95 Approximation::Inexact(v2, e) => Approximation::Inexact(v2, e),
96 },
97 Self::Inexact(v, e) => match f(v) {
98 Approximation::Exact(v2) => Approximation::Inexact(v2, e),
99 Approximation::Inexact(v2, e2) => Approximation::Inexact(v2, e2),
100 },
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::Approximation;
108
109 #[test]
110 fn value_with_exact() {
111 assert_eq!(Approximation::<i32, ()>::Exact(3).value_with_exact(), (3, true));
112 assert_eq!(Approximation::<i32, ()>::Inexact(3, ()).value_with_exact(), (3, false));
113 let (v, is_exact) = Approximation::<i32, &str>::Inexact(7, "err").value_with_exact();
115 assert_eq!(v, 7);
116 assert!(!is_exact);
117 }
118}