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}