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 {}