1use core::convert::Infallible;
2use core::num::{self, FpCategory, Saturating, Wrapping};
3use core::ops::Deref;
4use core::pin::Pin;
5
6use crate::filters::Either;
7use crate::{Result, impl_for_ref};
8
9#[inline]
12pub fn assigned_or<L: DefaultFilterable, R>(
13 value: &L,
14 fallback: R,
15) -> Result<Either<L::Filtered<'_>, R>, L::Error> {
16 match value.as_filtered()? {
17 Some(value) => Ok(Either::Left(value)),
18 None => Ok(Either::Right(fallback)),
19 }
20}
21
22#[diagnostic::on_unimplemented(
27 label = "`{Self}` is not `|assigned_or` filterable",
28 message = "`{Self}` is not `|assigned_or` filterable"
29)]
30pub trait DefaultFilterable {
31 type Filtered<'a>
33 where
34 Self: 'a;
35
36 type Error: Into<crate::Error>;
39
40 fn as_filtered(&self) -> Result<Option<Self::Filtered<'_>>, Self::Error>;
44}
45
46impl_for_ref! {
47 impl DefaultFilterable for T {
48 type Filtered<'a> = T::Filtered<'a>
49 where
50 Self: 'a;
51
52 type Error = T::Error;
53
54 #[inline]
55 fn as_filtered(&self) -> Result<Option<Self::Filtered<'_>>, Self::Error> {
56 <T>::as_filtered(self)
57 }
58 }
59}
60
61impl<T> DefaultFilterable for Pin<T>
63where
64 T: Deref,
65 <T as Deref>::Target: DefaultFilterable,
66{
67 type Filtered<'a>
68 = <<T as Deref>::Target as DefaultFilterable>::Filtered<'a>
69 where
70 Self: 'a;
71
72 type Error = <<T as Deref>::Target as DefaultFilterable>::Error;
73
74 #[inline]
75 fn as_filtered(&self) -> Result<Option<Self::Filtered<'_>>, Self::Error> {
76 self.as_ref().get_ref().as_filtered()
77 }
78}
79
80impl<T> DefaultFilterable for Option<T> {
82 type Filtered<'a>
83 = &'a T
84 where
85 Self: 'a;
86
87 type Error = Infallible;
88
89 #[inline]
90 fn as_filtered(&self) -> Result<Option<&T>, Infallible> {
91 Ok(self.as_ref())
92 }
93}
94
95impl<T, E> DefaultFilterable for Result<T, E> {
97 type Filtered<'a>
98 = &'a T
99 where
100 Self: 'a;
101
102 type Error = Infallible;
103
104 #[inline]
105 fn as_filtered(&self) -> Result<Option<&T>, Infallible> {
106 Ok(self.as_ref().ok())
107 }
108}
109
110impl DefaultFilterable for str {
112 type Filtered<'a>
113 = &'a str
114 where
115 Self: 'a;
116
117 type Error = Infallible;
118
119 #[inline]
120 fn as_filtered(&self) -> Result<Option<&str>, Infallible> {
121 match self.is_empty() {
122 false => Ok(Some(self)),
123 true => Ok(None),
124 }
125 }
126}
127
128#[cfg(feature = "alloc")]
130impl DefaultFilterable for alloc::string::String {
131 type Filtered<'a>
132 = &'a str
133 where
134 Self: 'a;
135
136 type Error = Infallible;
137
138 #[inline]
139 fn as_filtered(&self) -> Result<Option<&str>, Infallible> {
140 self.as_str().as_filtered()
141 }
142}
143
144#[cfg(feature = "alloc")]
146impl<T: DefaultFilterable + alloc::borrow::ToOwned + ?Sized> DefaultFilterable
147 for alloc::borrow::Cow<'_, T>
148{
149 type Filtered<'a>
150 = T::Filtered<'a>
151 where
152 Self: 'a;
153
154 type Error = T::Error;
155
156 #[inline]
157 fn as_filtered(&self) -> Result<Option<Self::Filtered<'_>>, Self::Error> {
158 self.as_ref().as_filtered()
159 }
160}
161
162impl<T: DefaultFilterable> DefaultFilterable for Wrapping<T> {
164 type Filtered<'a>
165 = T::Filtered<'a>
166 where
167 Self: 'a;
168
169 type Error = T::Error;
170
171 #[inline]
172 fn as_filtered(&self) -> Result<Option<Self::Filtered<'_>>, Self::Error> {
173 self.0.as_filtered()
174 }
175}
176
177impl<T: DefaultFilterable> DefaultFilterable for Saturating<T> {
179 type Filtered<'a>
180 = T::Filtered<'a>
181 where
182 Self: 'a;
183
184 type Error = T::Error;
185
186 #[inline]
187 fn as_filtered(&self) -> Result<Option<Self::Filtered<'_>>, Self::Error> {
188 self.0.as_filtered()
189 }
190}
191
192macro_rules! impl_for_int {
193 ($($name:ident : $ty:ty)*) => { $(
194 #[doc = concat!("A [`", stringify!($ty), "`] has a value if it is not `0`.")]
195 impl DefaultFilterable for $ty {
196 type Filtered<'a> = $ty;
197 type Error = Infallible;
198
199 #[inline]
200 fn as_filtered(&self) -> Result<Option<$ty>, Infallible> {
201 match *self {
202 0 => Ok(None),
203 value => Ok(Some(value)),
204 }
205 }
206 }
207
208 #[doc = concat!("A [`", stringify!($name), "`][num::", stringify!($name),"] always has a value.")]
209 impl DefaultFilterable for num::$name {
210 type Filtered<'a> = $ty;
211 type Error = Infallible;
212
213 #[inline]
214 fn as_filtered(&self) -> Result<Option<$ty>, Infallible> {
215 Ok(Some(self.get()))
216 }
217 }
218 )* };
219}
220
221impl_for_int!(
222 NonZeroU8:u8 NonZeroU16:u16 NonZeroU32:u32 NonZeroU64:u64 NonZeroU128:u128 NonZeroUsize:usize
223 NonZeroI8:i8 NonZeroI16:i16 NonZeroI32:i32 NonZeroI64:i64 NonZeroI128:i128 NonZeroIsize:isize
224);
225
226impl DefaultFilterable for bool {
228 type Filtered<'a> = bool;
229 type Error = Infallible;
230
231 #[inline]
232 fn as_filtered(&self) -> Result<Option<bool>, Infallible> {
233 match *self {
234 true => Ok(Some(true)),
235 false => Ok(None),
236 }
237 }
238}
239
240macro_rules! impl_for_float {
241 ($($ty:ty)*) => { $(
242 #[doc = concat!(
243 "An [`",
244 stringify!($ty),
245 "`] has a value if it is [`Normal`][FpCategory::Normal], i.e. it is not zero, \
246 not sub-normal, not infinite and not NaN."
247 )]
248 impl DefaultFilterable for $ty {
249 type Filtered<'a>
250 = Self
251 where
252 Self: 'a;
253
254 type Error = Infallible;
255
256 #[inline]
257 fn as_filtered(&self) -> Result<Option<Self::Filtered<'_>>, Self::Error> {
258 Ok((self.classify() == FpCategory::Normal).then_some(*self))
259 }
260 }
261 )* }
262}
263
264impl_for_float!(f32 f64);
265
266#[test]
267#[cfg(feature = "std")]
268fn test_default_filterable() {
269 use std::borrow::Cow;
270 use std::rc::Rc;
271 use std::string::ToString;
272 use std::sync::{Arc, Mutex};
273
274 use assert_matches::assert_matches;
275
276 assert_matches!(0_u8.as_filtered(), Ok(None));
278 assert_matches!(0_u16.as_filtered(), Ok(None));
279 assert_matches!(0_u32.as_filtered(), Ok(None));
280 assert_matches!(0_u64.as_filtered(), Ok(None));
281 assert_matches!(0_u128.as_filtered(), Ok(None));
282 assert_matches!(0_usize.as_filtered(), Ok(None));
283 assert_matches!(0_i8.as_filtered(), Ok(None));
284 assert_matches!(0_i16.as_filtered(), Ok(None));
285 assert_matches!(0_i32.as_filtered(), Ok(None));
286 assert_matches!(0_i64.as_filtered(), Ok(None));
287 assert_matches!(0_i128.as_filtered(), Ok(None));
288 assert_matches!(0_isize.as_filtered(), Ok(None));
289 assert_matches!(1_u8.as_filtered(), Ok(Some(1)));
290 assert_matches!(1_u16.as_filtered(), Ok(Some(1)));
291 assert_matches!(1_u32.as_filtered(), Ok(Some(1)));
292 assert_matches!(1_u64.as_filtered(), Ok(Some(1)));
293 assert_matches!(1_u128.as_filtered(), Ok(Some(1)));
294 assert_matches!(1_usize.as_filtered(), Ok(Some(1)));
295 assert_matches!(1_i8.as_filtered(), Ok(Some(1)));
296 assert_matches!(1_i16.as_filtered(), Ok(Some(1)));
297 assert_matches!(1_i32.as_filtered(), Ok(Some(1)));
298 assert_matches!(1_i64.as_filtered(), Ok(Some(1)));
299 assert_matches!(1_i128.as_filtered(), Ok(Some(1)));
300 assert_matches!(1_isize.as_filtered(), Ok(Some(1)));
301 assert_matches!((-1_i8).as_filtered(), Ok(Some(-1)));
302 assert_matches!((-1_i16).as_filtered(), Ok(Some(-1)));
303 assert_matches!((-1_i32).as_filtered(), Ok(Some(-1)));
304 assert_matches!((-1_i64).as_filtered(), Ok(Some(-1)));
305 assert_matches!((-1_i128).as_filtered(), Ok(Some(-1)));
306 assert_matches!((-1_isize).as_filtered(), Ok(Some(-1)));
307
308 assert_matches!(0_f32.as_filtered(), Ok(None));
311 assert_matches!(0_f64.as_filtered(), Ok(None));
312 assert_matches!((f32::MIN_POSITIVE / 2.0).as_filtered(), Ok(None));
314 assert_matches!((f64::MIN_POSITIVE / 2.0).as_filtered(), Ok(None));
315 assert_matches!(f32::NAN.as_filtered(), Ok(None));
317 assert_matches!(f64::NAN.as_filtered(), Ok(None));
318 assert_matches!(f32::NEG_INFINITY.as_filtered(), Ok(None));
320 assert_matches!(f32::INFINITY.as_filtered(), Ok(None));
321 assert_matches!(f64::NEG_INFINITY.as_filtered(), Ok(None));
322 assert_matches!(f64::INFINITY.as_filtered(), Ok(None));
323 assert_matches!(1_f32.as_filtered(), Ok(Some(1.0)));
325 assert_matches!((-1_f32).as_filtered(), Ok(Some(-1.0)));
326 assert_matches!(f32::MIN.as_filtered(), Ok(Some(f32::MIN)));
327 assert_matches!(f32::MIN_POSITIVE.as_filtered(), Ok(Some(f32::MIN_POSITIVE)));
328 assert_matches!(f32::MAX.as_filtered(), Ok(Some(f32::MAX)));
329 assert_matches!(1_f64.as_filtered(), Ok(Some(1.0)));
330 assert_matches!((-1_f64).as_filtered(), Ok(Some(-1.0)));
331 assert_matches!(f64::MIN.as_filtered(), Ok(Some(f64::MIN)));
332 assert_matches!(f64::MIN_POSITIVE.as_filtered(), Ok(Some(f64::MIN_POSITIVE)));
333 assert_matches!(f64::MAX.as_filtered(), Ok(Some(f64::MAX)));
334
335 assert_matches!(num::NonZeroU8::new(1).unwrap().as_filtered(), Ok(Some(1)));
337 assert_matches!(num::NonZeroU16::new(1).unwrap().as_filtered(), Ok(Some(1)));
338 assert_matches!(num::NonZeroU32::new(1).unwrap().as_filtered(), Ok(Some(1)));
339 assert_matches!(num::NonZeroU64::new(1).unwrap().as_filtered(), Ok(Some(1)));
340 assert_matches!(num::NonZeroU128::new(1).unwrap().as_filtered(), Ok(Some(1)));
341 assert_matches!(
342 num::NonZeroUsize::new(1).unwrap().as_filtered(),
343 Ok(Some(1))
344 );
345 assert_matches!(num::NonZeroI8::new(1).unwrap().as_filtered(), Ok(Some(1)));
346 assert_matches!(num::NonZeroI16::new(1).unwrap().as_filtered(), Ok(Some(1)));
347 assert_matches!(num::NonZeroI32::new(1).unwrap().as_filtered(), Ok(Some(1)));
348 assert_matches!(num::NonZeroI64::new(1).unwrap().as_filtered(), Ok(Some(1)));
349 assert_matches!(num::NonZeroI128::new(1).unwrap().as_filtered(), Ok(Some(1)));
350 assert_matches!(
351 num::NonZeroIsize::new(1).unwrap().as_filtered(),
352 Ok(Some(1))
353 );
354
355 assert_matches!("".as_filtered(), Ok(None));
357 assert_matches!("hello".as_filtered(), Ok(Some("hello")));
358 assert_matches!("".to_string().as_filtered(), Ok(None));
359 assert_matches!("hello".to_string().as_filtered(), Ok(Some("hello")));
360 assert_matches!(Cow::Borrowed("").as_filtered(), Ok(None));
361 assert_matches!(Cow::Borrowed("hello").as_filtered(), Ok(Some("hello")));
362 assert_matches!(Cow::<str>::Owned("".to_string()).as_filtered(), Ok(None));
363 assert_matches!(
364 Cow::<str>::Owned("hello".to_string()).as_filtered(),
365 Ok(Some("hello"))
366 );
367
368 assert_matches!(Ok::<(), ()>(()).as_filtered(), Ok(Some(())));
370 assert_matches!(Err::<(), ()>(()).as_filtered(), Ok(None));
371 assert_matches!(Some(()).as_filtered(), Ok(Some(())));
372 assert_matches!(None::<()>.as_filtered(), Ok(None));
373
374 assert_matches!(Arc::new("").as_filtered(), Ok(None));
376 assert_matches!(Arc::new("hello").as_filtered(), Ok(Some("hello")));
377 assert_matches!(Arc::pin("").as_filtered(), Ok(None));
378 assert_matches!(Arc::pin("hello").as_filtered(), Ok(Some("hello")));
379 assert_matches!(Rc::new("").as_filtered(), Ok(None));
380 assert_matches!(Rc::new("hello").as_filtered(), Ok(Some("hello")));
381 assert_matches!(Rc::pin("").as_filtered(), Ok(None));
382 assert_matches!(Rc::pin("hello").as_filtered(), Ok(Some("hello")));
383 assert_matches!(Mutex::new("").try_lock().unwrap().as_filtered(), Ok(None));
384 assert_matches!(
385 Mutex::new("hello").try_lock().unwrap().as_filtered(),
386 Ok(Some("hello"))
387 );
388}