unit_ext/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3
4/// Extension methods for the unit type `()` that construct common wrapper
5/// values without explicit boiler-plate.
6///
7/// Import [`unit_ext`](crate) to bring the trait into scope.
8///
9/// # Examples
10///
11/// ```
12/// use unit_ext::*;
13///
14/// let ok:  Result<_, ()> = ().ret_ok(1);
15/// let err: Result<u8, _> = ().ret_err("boom");
16///
17/// let some = ().ret_some("hi");
18/// let none: Option<i32> = ().ret_none();
19///
20/// let vec: Vec<u8> = ().ret_default();
21/// ```
22pub trait UnitExt: Sized {
23    /// Returns `value`.
24    ///
25    /// This is mainly useful when syntactic symmetry with the other
26    /// `ret_*` helpers is desired.
27    ///
28    /// # Examples
29    ///
30    /// ```
31    /// use unit_ext::*;
32    /// assert_eq!(().ret(42), 42);
33    /// assert_eq!({ 24; }.ret(42), 42); // Can cause a Clippy warning/error.
34    /// assert_eq!(println!("24").ret(42), 42);
35    /// ```
36    #[must_use]
37    #[inline]
38    fn ret<T>(self, value: T) -> T {
39        value
40    }
41
42    /// Returns `T::default()`.
43    ///
44    /// # Examples
45    ///
46    /// ```
47    /// use unit_ext::*;
48    /// let v: Vec<u8> = println!("Creating empty vec").ret_default();
49    /// assert!(v.is_empty());
50    /// ```
51    #[must_use]
52    #[inline]
53    fn ret_default<T: Default>(self) -> T {
54        T::default()
55    }
56
57    /// Returns [`None`].
58    ///
59    /// # Examples
60    ///
61    /// ```
62    /// use unit_ext::*;
63    /// let none = ().ret_none::<u8>();
64    /// assert_eq!(none, None);
65    /// ```
66    #[must_use]
67    #[inline]
68    fn ret_none<T>(self) -> Option<T> {
69        None
70    }
71
72    /// Wraps `value` in [`Some`] and returns it.
73    ///
74    /// `value` is passed through `Into`, matching the behaviour of
75    /// `Option::from`.
76    ///
77    /// # Examples
78    ///
79    /// ```
80    /// use unit_ext::*;
81    /// let opt = ().ret_some(5);
82    /// assert_eq!(opt, Some(5));
83    /// ```
84    #[must_use]
85    #[inline]
86    fn ret_some<T>(self, value: T) -> Option<T> {
87        value.into()
88    }
89
90    /// Returns `Some(T::default())`.
91    ///
92    /// # Examples
93    ///
94    /// ```
95    /// use unit_ext::*;
96    /// let s: Option<String> = ().ret_some_default();
97    /// assert_eq!(s, Some(String::new()));
98    /// ```
99    #[must_use]
100    #[inline]
101    fn ret_some_default<T: Default>(self) -> Option<T> {
102        self.ret_default::<T>().into()
103    }
104
105    /// Returns `Err(value)`.
106    ///
107    /// # Examples
108    ///
109    /// ```
110    /// use unit_ext::*;
111    /// let e: Result<(), &str> = ().ret_err("nope");
112    /// assert!(e.is_err());
113    /// ```
114    #[must_use]
115    #[inline]
116    fn ret_err<T, E>(self, value: E) -> Result<T, E> {
117        Err(value)
118    }
119
120    /// Returns `Err(E::default())`.
121    ///
122    /// # Examples
123    ///
124    /// ```
125    /// use unit_ext::*;
126    /// let e: Result<i32, &str> = ().ret_err_default();
127    /// assert!(e.is_err());
128    /// ```
129    #[must_use]
130    #[inline]
131    fn ret_err_default<T, E: Default>(self) -> Result<T, E> {
132        self.ret_err(E::default())
133    }
134
135    /// Returns `Ok(value)`.
136    ///
137    /// # Examples
138    ///
139    /// ```
140    /// use unit_ext::*;
141    /// let ok = ().ret_ok::<_, ()>("yes");
142    /// assert_eq!(ok, Ok("yes"));
143    /// ```
144    #[must_use]
145    #[inline]
146    fn ret_ok<T, E>(self, value: T) -> Result<T, E> {
147        Ok(value)
148    }
149
150    /// Returns `Ok(T::default())`.
151    ///
152    /// # Examples
153    ///
154    /// ```
155    /// use unit_ext::*;
156    /// let ok: Result<Vec<u8>, ()> = ().ret_ok_default();
157    /// assert_eq!(ok, Ok(Vec::new()));
158    /// ```
159    #[must_use]
160    #[inline]
161    fn ret_ok_default<T: Default, E>(self) -> Result<T, E> {
162        self.ret_ok(T::default())
163    }
164}
165
166/// Extension methods for any value that explicitly discard the value
167/// and yield unit `()`.
168///
169/// The helpers make intent obvious when chaining iterator or async
170/// pipelines.
171///
172/// # Examples
173///
174/// ```
175/// use unit_ext::*;
176///
177/// (0..3).for_each(|n| n.discard_ret());
178/// let x: Option<usize> = Some(0).discard_self().ret_some(1);
179/// ```
180pub trait RetExt: Sized {
181    /// Discards `self`, returning `()`.
182    ///
183    /// Equivalent to `let _ = self;`.
184    #[inline]
185    fn discard_self(self) {
186        let _ = self;
187    }
188
189    /// Alias for [`discard_self`](RetExt::discard_self)
190    #[inline]
191    fn discard_ret(self) {
192        self.discard_self();
193    }
194}
195
196impl UnitExt for () {}
197impl<T> RetExt for T {}