quantified/
lib.rs

1#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
2pub enum Quantified<T> {
3    None,
4    Some(T),
5    Excluding(T),
6    All,
7}
8
9impl<T> Quantified<T> {
10    /// Maps an `Quantified<T>` to `Quantified<U>` by applying a function to a contained `Some`
11    /// or `Excluding` value.
12    ///
13    /// # Examples
14    ///
15    /// Converts an `Quantified<`[`String`]`>` into an `Quantified<`[`usize`]`>`, consuming
16    /// the original:
17    ///
18    /// [`String`]: ../../std/string/struct.String.html
19    /// ```
20    /// # use quantified::Quantified;
21    /// let some_string = Quantified::Some(String::from("Hello, World!"));
22    /// // `Quantified::map` takes self *by value*, consuming `maybe_some_string`
23    /// let some_len = some_string.map(|s| s.len());
24    ///
25    /// assert_eq!(some_len, Quantified::Some(13));
26    /// ```
27    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Quantified<U> {
28        match self {
29            Self::Some(x) => Quantified::Some(f(x)),
30            Self::Excluding(x) => Quantified::Excluding(f(x)),
31            Self::None => Quantified::None,
32            Self::All => Quantified::All,
33        }
34    }
35
36    /// Converts from `&Quantified<T>` to `Quantified<&T>`.
37    ///
38    /// # Examples
39    ///
40    /// Converts a `Quantified<`[`String`]`>` into a `Quantified<`[`usize`]`>`,
41    /// preserving the original.
42    /// The [`map`] method takes the `self` argument by value, consuming the original,
43    /// so this technique uses `as_ref` to first take a `Quantified` to a reference
44    /// to the value inside the original.
45    ///
46    /// [`map`]: Quantified::map
47    /// [`String`]: ../../std/string/struct.String.html
48    ///
49    /// ```
50    /// # use quantified::Quantified;
51    /// let text: Quantified<String> = Quantified::Some("Hello, world!".to_string());
52    /// // First, cast `Quantified<String>` to `Quantified<&String>` with `as_ref`,
53    /// // then consume *that* with `map`, leaving `text` on the stack.
54    /// let text_length: Quantified<usize> = text.as_ref().map(|s| s.len());
55    /// println!("still can print text: {:?}", text);
56    /// ```
57    pub const fn as_ref(&self) -> Quantified<&T> {
58        match self {
59            Self::None => Quantified::None,
60            Self::Some(x) => Quantified::Some(&x),
61            Self::Excluding(x) => Quantified::Excluding(&x),
62            Self::All => Quantified::All,
63        }
64    }
65
66    /// Converts from `&mut Quantified<T>` to `Quantified<&mut T>`.
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// # use quantified::Quantified;
72    /// let mut x = Some(2);
73    /// match x.as_mut() {
74    ///     Some(v) => *v = 42,
75    ///     None => {},
76    /// }
77    /// assert_eq!(x, Some(42));
78    /// ```
79    pub fn as_mut(&mut self) -> Quantified<&mut T> {
80        match self {
81            Self::None => Quantified::None,
82            Self::Some(ts) => Quantified::Some(ts),
83            Self::Excluding(ts) => Quantified::Excluding(ts),
84            Self::All => Quantified::All,
85        }
86    }
87}
88
89impl<T: std::ops::Deref> Quantified<T> {
90    /// Converts from `Quantified<T>` (or `&Quantified<T>`) to `Quantified<&T::Target>`.
91    ///
92    /// Leaves the original `Quantified` in-place, creating a new one with a reference
93    /// to the original one, additionally coercing the contents via [`Deref`].
94    ///
95    /// # Examples
96    ///
97    /// ```
98    /// # use quantified::Quantified;
99    /// let x: Quantified<String> = Quantified::Some("hey".to_owned());
100    /// assert_eq!(x.as_deref(), Quantified::Some("hey"));
101    ///
102    /// let x: Quantified<String> = Quantified::All;
103    /// assert_eq!(x.as_deref(), Quantified::All);
104    /// ```
105    pub fn as_deref(&self) -> Quantified<&T::Target> {
106        self.as_ref().map(|t| t.deref())
107    }
108}
109
110impl<T: std::ops::DerefMut> Quantified<T> {
111    /// Converts from `Quantified<T>` (or `&mut Quantified<T>`) to `Quantified<&mut T::Target>`.
112    ///
113    /// Leaves the original `Quantified` in-place, creating a new one containing a mutable
114    /// reference to the inner type's `Deref::Target` type.
115    ///
116    /// # Examples
117    ///
118    /// ```
119    /// # use quantified::Quantified;
120    /// let mut x: Quantified<String> = Quantified::Excluding("hey".to_owned());
121    /// assert_eq!(x.as_deref_mut().map(|x| {
122    ///     x.make_ascii_uppercase();
123    ///     x
124    /// }), Quantified::Excluding("HEY".to_owned().as_mut_str()));
125    /// ```
126    pub fn as_deref_mut(&mut self) -> Quantified<&mut T::Target> {
127        self.as_mut().map(|t| t.deref_mut())
128    }
129}