nullable_result/
lib.rs

1//! ## Contents
2//! * [NullableResult] - the core of this crate
3//! * the [extract] macro - early return from functions `?`-style
4//! * [iterator extension](IterExt) - additional methods for iterators over [NullableResult]
5//! * [general iterator extension](GeneralIterExt) - additional methods for all iterators
6//! * [MaybeTryFrom] and [MaybeTryInto] - analogues of [TryFrom] and [TryInto]
7
8#![warn(missing_docs)]
9#![cfg_attr(not(feature = "std"), no_std)]
10#![cfg_attr(not(feature = "__unstable"), forbid(unstable_features))]
11#![cfg_attr(feature = "try_trait", feature(try_trait_v2))]
12
13#[cfg(feature = "try_trait")]
14mod try_trait;
15
16use self::NullableResult::*;
17#[cfg(doc)]
18use core::convert::TryInto;
19use core::{
20    convert::TryFrom,
21    fmt::Debug,
22    iter::{FilterMap, FromIterator, FusedIterator},
23    ops::Deref,
24};
25
26/// A replacement for `Option<Result<T, E>>` or `Result<Option<T>, E>`.
27///
28/// Sometimes, no value returned from an operation is not an error. It's a special
29/// case that needs to be handled, but it's separate from error handling. Wrapping
30/// an [`Option`] in a [`Result`] or vice versa can get very confusing very fast. Instead,
31/// use a [`NullableResult`].
32///
33/// This is how it's defined:
34/// ```rust
35/// pub enum NullableResult<T, E> {
36///     Ok(T),
37///     Err(E),
38///     Null,
39/// }
40/// ```
41///
42/// ## Convert to and From std Types
43///
44/// It defines the [`From`] trait for `Option<Result<T, E>>` and for
45/// `Result<Option<T>, E>` in both directions, so you can easily convert between the
46/// standard library types and back.
47/// ```rust
48/// # use nullable_result::NullableResult;
49/// let opt_res: Option<Result<usize, isize>> = Some(Ok(4));
50/// let nr: NullableResult<usize, isize> = NullableResult::from(opt_res);
51/// let opt_res: Option<Result<_,_>> = nr.into();
52/// ```
53/// It also defines [`From`] for [`Option<T>] and for [`Result<T, E>`].
54/// ```rust
55/// # use nullable_result::NullableResult;
56/// let nr: NullableResult<_, isize> = NullableResult::from(Some(4));
57/// let result: Result<usize, isize> = Ok(4);
58/// let nr = NullableResult::from(result);
59/// ```
60///
61/// ## Unwrapping Conversions
62/// There are also methods for unwrapping conversions. (i.e. convert to `Option<T>` or
63/// `Result<T, E>`. When converting a a `Result`, you need to provide an error value
64/// in case the `NullableResult` contains `Null`.
65/// ```rust
66/// # use nullable_result::NullableResult;
67/// let nr = NullableResult::<usize, isize>::Ok(5);
68/// let opt = nr.option();
69/// let res = nr.result(-5);
70/// ```
71///
72/// There are also a few convenience methods.
73/// ```rust
74/// # use nullable_result::NullableResult;
75/// let nr: NullableResult<usize, isize> = NullableResult::Ok(4);
76/// let _ : Option<Result<usize, isize>> = nr.optional_result();
77/// let _: Result<Option<usize>, isize> = nr.resulting_option();
78/// let _: Result<usize, Option<isize>> = nr.result_optional_err();
79/// let _: Result<usize, isize> = nr.result(-5); // need to provide default error value
80/// let _: Result<usize, isize> = nr.result_with(|| 5 - 10); //closure that returns a default error
81/// ```
82#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
83#[must_use]
84pub enum NullableResult<T, E> {
85    /// Contains the success value
86    Ok(T),
87    /// Contains the error value
88    Err(E),
89    /// No value
90    Null,
91}
92
93impl<T, E> Default for NullableResult<T, E> {
94    /// The default value is `Null`
95    fn default() -> Self {
96        Null
97    }
98}
99
100impl<T, E: Debug> NullableResult<T, E> {
101    /// Panics if it's not `Ok`, otherwise returns the contained value.
102    #[inline]
103    pub fn unwrap(self) -> T {
104        match self {
105            NullableResult::Ok(item) => item,
106            NullableResult::Err(err) => panic!(
107                "tried to unwrap a nullable result containing Err: {:?}",
108                err
109            ),
110            NullableResult::Null => {
111                panic!("tried to unwrap a nullable result containing `Null`")
112            }
113        }
114    }
115}
116
117impl<T: Default, E> NullableResult<T, E> {
118    /// Returns the contained value if it's `Ok`, otherwise returns the default value
119    /// for that type.
120    #[inline]
121    pub fn unwrap_or_default(self) -> T {
122        match self {
123            Ok(item) => item,
124            _ => T::default(),
125        }
126    }
127}
128
129impl<T: Copy, E> NullableResult<&'_ T, E> {
130    /// Returns a `NullableResult` with the `Ok` part copied.
131    #[inline]
132    pub fn copied(self) -> NullableResult<T, E> {
133        self.map(|&item| item)
134    }
135}
136
137impl<T: Copy, E> NullableResult<&'_ mut T, E> {
138    /// Returns a `NullableResult` with the `Ok` part copied.
139    #[inline]
140    pub fn copied(self) -> NullableResult<T, E> {
141        self.map(|&mut item| item)
142    }
143}
144
145impl<T: Clone, E> NullableResult<&'_ T, E> {
146    /// Returns a `NullableResult` with the `Ok` part cloned.
147    #[inline]
148    pub fn cloned(self) -> NullableResult<T, E> {
149        self.map(|item| item.clone())
150    }
151}
152
153impl<T: Clone, E> NullableResult<&'_ mut T, E> {
154    /// Returns a `NullableResult` with the `Ok` part cloned.
155    #[inline]
156    pub fn cloned(self) -> NullableResult<T, E> {
157        self.map(|item| item.clone())
158    }
159}
160
161impl<T: Deref, E> NullableResult<T, E> {
162    /// Coerce the `Ok` variant of the original result with `Deref` and returns the
163    /// new `NullableResult`
164    #[inline]
165    pub fn as_deref(&self) -> NullableResult<&T::Target, &E> {
166        match self {
167            Ok(item) => Ok(item.deref()),
168            Err(err) => Err(err),
169            Null => Null,
170        }
171    }
172}
173
174impl<T, E> NullableResult<T, E> {
175    /// Returns `true` if this result is an [`Ok`] value
176    #[inline]
177    #[must_use]
178    pub fn is_ok(&self) -> bool {
179        matches!(self, Ok(_))
180    }
181
182    /// Returns `true` if this result is an [`Err`] value
183    #[inline]
184    #[must_use]
185    pub fn is_err(&self) -> bool {
186        matches!(self, Err(_))
187    }
188
189    /// Returns `true` if this result is a [`Null`] value
190    #[inline]
191    #[must_use]
192    pub fn is_null(&self) -> bool {
193        matches!(self, Null)
194    }
195
196    /// Returns the contained [`Ok`] value, consuming `self`.
197    ///
198    /// # Panics
199    /// Panics if the value is not [`Ok`] with the provided message.
200    #[inline]
201    #[track_caller]
202    pub fn expect(self, msg: &str) -> T {
203        match self {
204            Ok(item) => item,
205            _ => panic!("{}", msg),
206        }
207    }
208
209    /// Returns the contained value if it's `Ok`, returns `item` otherwise.
210    #[inline]
211    pub fn unwrap_or(self, item: T) -> T {
212        match self {
213            Ok(item) => item,
214            _ => item,
215        }
216    }
217
218    /// Returns the contained value if it's `Ok`, otherwise, it calls `f` and forwards
219    /// its return value.
220    #[inline]
221    pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
222        match self {
223            Ok(item) => item,
224            _ => f(),
225        }
226    }
227
228    /// Returns an `Option<T>` consuming `self`, returns `Null` if the `NullableResult`
229    /// contains `Err`.
230    #[inline]
231    pub fn option(self) -> Option<T> {
232        match self {
233            Ok(item) => Some(item),
234            Err(_) | Null => None,
235        }
236    }
237
238    /// Return an `Option<Result<T, E>>` consuming `self`.
239    #[inline]
240    pub fn optional_result(self) -> Option<Result<T, E>> {
241        self.into()
242    }
243
244    /// Return a `Result<Option<T>, E>` consuming `self`.
245    #[inline]
246    pub fn resulting_option(self) -> Result<Option<T>, E> {
247        self.into()
248    }
249
250    /// Returns a `Result<T, E>`, returns the provided `err` if the `NullableResult`
251    /// contains `Null`
252    #[inline]
253    pub fn result(self, err: E) -> Result<T, E> {
254        match self {
255            Ok(item) => Result::Ok(item),
256            Err(err) => Result::Err(err),
257            Null => Result::Err(err),
258        }
259    }
260
261    /// Returns a `Result<T, E>`, if the `NullableResult` contains `Ok` or `Err`, the
262    /// value is returned, otherwise, returns the result of `f`.
263    #[inline]
264    pub fn result_with<F: FnOnce() -> E>(self, f: F) -> Result<T, E> {
265        match self {
266            Ok(item) => Result::Ok(item),
267            Err(err) => Result::Err(err),
268            Null => Result::Err(f()),
269        }
270    }
271
272    /// Maps to a `NullableResult` with a different ok type.
273    #[inline]
274    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> NullableResult<U, E> {
275        match self {
276            Ok(item) => Ok(f(item)),
277            Err(err) => Err(err),
278            Null => Null,
279        }
280    }
281
282    /// Maps to a `NullableResult` with a different err type.
283    #[inline]
284    pub fn map_err<U, F: FnOnce(E) -> U>(self, f: F) -> NullableResult<T, U> {
285        match self {
286            Ok(item) => NullableResult::Ok(item),
287            Err(err) => NullableResult::Err(f(err)),
288            Null => NullableResult::Null,
289        }
290    }
291
292    /// Returns a [`Result`] with an optional error.
293    #[inline]
294    pub fn result_optional_err(self) -> Result<T, Option<E>> {
295        match self {
296            Ok(item) => Result::Ok(item),
297            Err(err) => Result::Err(Some(err)),
298            Null => Result::Err(None),
299        }
300    }
301
302    /// Convert from a `NullableResult<T, E>` or `&NullableResult<T, E>` to a
303    /// `NullableResult<&T, &E>`.
304    #[inline]
305    pub fn as_ref(&self) -> NullableResult<&T, &E> {
306        use NullableResult::*;
307        match self {
308            Ok(item) => Ok(item),
309            Err(err) => Err(err),
310            Null => Null,
311        }
312    }
313
314    /// Convert from a `mut NullableResult<T, E>` or `&mut NullableResult<T, E>` to a
315    /// `NullableResult<&mut T, &mut E>`.
316    #[inline]
317    pub fn as_mut(&mut self) -> NullableResult<&mut T, &mut E> {
318        use NullableResult::*;
319        match self {
320            Ok(item) => Ok(item),
321            Err(err) => Err(err),
322            Null => Null,
323        }
324    }
325
326    /// If `self` is [`Ok`], returns `res`, keeps the [`Err`] or [`Null`] from
327    /// `self` otherwise.
328    #[inline]
329    pub fn and<U>(self, res: NullableResult<U, E>) -> NullableResult<U, E> {
330        match self {
331            Ok(_) => res,
332            Err(err) => Err(err),
333            Null => Null,
334        }
335    }
336
337    /// Calls `op` if the result is [`Ok`], otherwise returns the [`Err`] or [`Null`]
338    /// from `self`.
339    #[inline]
340    pub fn and_then<U, F>(self, op: F) -> NullableResult<U, E>
341    where
342        F: FnOnce(T) -> NullableResult<U, E>,
343    {
344        match self {
345            Ok(item) => op(item),
346            Err(err) => Err(err),
347            Null => Null,
348        }
349    }
350}
351
352impl<T, E> NullableResult<NullableResult<T, E>, E> {
353    /// Convert from `NullableResult<NullableResult<T, E>, E>` to
354    /// `NullableResult<T, E>`.
355    #[inline]
356    pub fn flatten(self) -> NullableResult<T, E> {
357        match self {
358            Ok(Ok(item)) => Ok(item),
359            Ok(Err(err)) | Err(err) => Err(err),
360            Ok(Null) | Null => Null,
361        }
362    }
363}
364
365impl<T, E> From<Result<Option<T>, E>> for NullableResult<T, E> {
366    #[inline]
367    fn from(res: Result<Option<T>, E>) -> Self {
368        match res {
369            Result::Ok(Option::Some(item)) => Ok(item),
370            Result::Ok(None) => Null,
371            Result::Err(err) => Err(err),
372        }
373    }
374}
375
376impl<T, E> From<NullableResult<T, E>> for Result<Option<T>, E> {
377    #[inline]
378    fn from(nr: NullableResult<T, E>) -> Self {
379        match nr {
380            Ok(item) => Result::Ok(Some(item)),
381            Err(err) => Result::Err(err),
382            Null => Result::Ok(None),
383        }
384    }
385}
386
387impl<T, E> From<Result<T, E>> for NullableResult<T, E> {
388    #[inline]
389    fn from(res: Result<T, E>) -> Self {
390        match res {
391            Result::Ok(item) => Ok(item),
392            Result::Err(err) => Err(err),
393        }
394    }
395}
396
397impl<T, E> From<Option<Result<T, E>>> for NullableResult<T, E> {
398    #[inline]
399    fn from(opt: Option<Result<T, E>>) -> Self {
400        match opt {
401            None => Null,
402            Some(Result::Ok(item)) => Ok(item),
403            Some(Result::Err(err)) => Err(err),
404        }
405    }
406}
407
408impl<T, E> From<NullableResult<T, E>> for Option<Result<T, E>> {
409    #[inline]
410    fn from(nr: NullableResult<T, E>) -> Self {
411        match nr {
412            Ok(item) => Some(Result::Ok(item)),
413            Err(err) => Some(Result::Err(err)),
414            Null => None,
415        }
416    }
417}
418
419impl<T, E> From<Option<T>> for NullableResult<T, E> {
420    #[inline]
421    fn from(opt: Option<T>) -> Self {
422        match opt {
423            Some(item) => Ok(item),
424            None => Null,
425        }
426    }
427}
428
429impl<T, E> From<Result<T, Option<E>>> for NullableResult<T, E> {
430    #[inline]
431    fn from(res: Result<T, Option<E>>) -> Self {
432        match res {
433            Result::Ok(item) => Ok(item),
434            Result::Err(Some(err)) => Err(err),
435            Result::Err(None) => Null,
436        }
437    }
438}
439
440impl<T, E, C> FromIterator<NullableResult<T, E>> for NullableResult<C, E>
441where
442    C: FromIterator<T>,
443{
444    fn from_iter<I: IntoIterator<Item = NullableResult<T, E>>>(
445        iter: I,
446    ) -> Self {
447        let result = iter
448            .into_iter()
449            .map(NullableResult::result_optional_err)
450            .collect::<Result<_, _>>();
451
452        NullableResult::from(result)
453    }
454}
455
456/// This macro [`extract`] that works like the `?` operator and can be used in
457/// functions that return a [`NullableResult`] as long as the error type is the same.
458/// It takes a [`NullableResult`], a [`Result`], or an [`Option`]. If the input
459/// contains an `Ok` or `Some` value, the value is extracted and returned,
460/// if it contains an `Err` or `Null`, the function returns early with the `Err` or
461/// `Null` wrapped in a new `NullableResult`.
462/// ```rust
463/// # use nullable_result::{NullableResult, extract};
464/// fn do_a_thing() -> NullableResult<usize, isize> {
465///     let res = some_other_func();
466///     let number = extract!(res); // <---- this will cause the function to return early
467///     NullableResult::Ok(number as usize + 5)
468/// }
469///
470/// // note that the two functions have different types for their Ok values
471/// fn some_other_func() -> NullableResult<i8, isize> {
472///     NullableResult::Null
473/// }
474/// ```
475///
476/// If the input is an option, it requires a second parameter as a type annotation for
477/// converting to a ['NullableResult`]. Hopefully this won't be necessary in some
478/// future version.
479/// ```rust
480/// # use nullable_result::{NullableResult, extract};
481/// fn f() -> NullableResult<usize, isize> {
482///     let opt = Some(4_usize);
483///     let four = extract!(opt, isize);
484///     NullableResult::Ok(four)
485/// }
486/// ```
487#[macro_export]
488macro_rules! extract {
489    ($nr:expr) => {
490        extract!($nr, _)
491    };
492    ($nr:expr, $err:ty) => {{
493        let nr = $crate::NullableResult::<_, $err>::from($nr);
494        match nr {
495            $crate::NullableResult::Ok(item) => item,
496            $crate::NullableResult::Err(err) => {
497                return $crate::NullableResult::Err(err.into());
498            }
499            $crate::NullableResult::Null => {
500                return $crate::NullableResult::Null;
501            }
502        }
503    }};
504}
505
506/// Adds additional methods to all iterators.
507pub trait GeneralIterExt: Iterator {
508    /// Applies the predicate to the elements of the iterator and returns the first
509    /// true result or the first error.
510    fn try_find<E, P>(self, pred: P) -> NullableResult<Self::Item, E>
511    where
512        P: FnMut(&Self::Item) -> Result<bool, E>;
513
514    /// Applies the function to the elements of the iterator and returns the first
515    /// value that isn't [`Null`]
516    fn try_find_map<T, E, F>(self, f: F) -> NullableResult<T, E>
517    where
518        F: FnMut(Self::Item) -> NullableResult<T, E>;
519
520    /// Fold the elements of the iterator using the given initial value and operation.
521    /// Returns early if the operation does not return [`Ok`].
522    fn maybe_try_fold<T, E, Op>(
523        &mut self,
524        init: T,
525        op: Op,
526    ) -> NullableResult<T, E>
527    where
528        Op: FnMut(T, Self::Item) -> NullableResult<T, E>;
529}
530
531impl<I: Iterator> GeneralIterExt for I {
532    #[inline]
533    fn try_find<E, P>(self, mut pred: P) -> NullableResult<Self::Item, E>
534    where
535        P: FnMut(&Self::Item) -> Result<bool, E>,
536    {
537        for item in self {
538            return match pred(&item) {
539                Result::Err(err) => Err(err),
540                Result::Ok(true) => Ok(item),
541                Result::Ok(false) => continue,
542            };
543        }
544        Null
545    }
546
547    #[inline]
548    fn try_find_map<T, E, F>(self, mut f: F) -> NullableResult<T, E>
549    where
550        F: FnMut(Self::Item) -> NullableResult<T, E>,
551    {
552        for item in self {
553            return match f(item) {
554                Ok(item) => Ok(item),
555                Err(err) => Err(err),
556                Null => continue,
557            };
558        }
559        Null
560    }
561
562    #[inline]
563    fn maybe_try_fold<T, E, Op>(
564        &mut self,
565        init: T,
566        mut op: Op,
567    ) -> NullableResult<T, E>
568    where
569        Op: FnMut(T, Self::Item) -> NullableResult<T, E>,
570    {
571        self.try_fold(init, |prev, curr| op(prev, curr).result_optional_err())
572            .into()
573    }
574}
575
576/// Additional methods for iterators over [`NullableResult`]
577pub trait IterExt<T, E>: Iterator<Item = NullableResult<T, E>>
578where
579    Self: Sized,
580{
581    /// Filter out all the null values. Returns an iterator over [`Result<T, E>`].
582    #[inline]
583    fn filter_nulls(self) -> FilterNulls<Self, T, E> {
584        self.filter_map(Option::from)
585    }
586
587    /// Returns the first value that is an [`Err`] or that the predicate accepts.
588    #[inline]
589    fn extract_and_find<P>(self, mut pred: P) -> NullableResult<T, E>
590    where
591        P: FnMut(&T) -> Result<bool, E>,
592    {
593        self.try_find_map(|item| {
594            let item = extract!(item);
595            match pred(&item) {
596                Result::Err(err) => Err(err),
597                Result::Ok(true) => Ok(item),
598                Result::Ok(false) => Null,
599            }
600        })
601    }
602
603    /// Applies the function to each element until it finds one that the function
604    /// returns [`Ok`] or [`Err`] and returns that value.
605    #[inline]
606    fn extract_and_find_map<F, U>(self, mut f: F) -> NullableResult<U, E>
607    where
608        F: FnMut(T) -> NullableResult<U, E>,
609    {
610        self.try_find_map(|item| f(extract!(item)))
611    }
612
613    /// Returns an iterator that applies the predicate to each element and filters out
614    /// the values for which it returns false.
615    #[inline]
616    fn try_filter<P>(self, pred: P) -> TryFilter<Self, P, T, E>
617    where
618        P: FnMut(&T) -> bool,
619    {
620        TryFilter { inner: self, pred }
621    }
622
623    /// Returns an iterator that both filters and maps.
624    fn try_filter_map<F, U>(self, f: F) -> TryFilterMap<Self, F, T, U, E>
625    where
626        F: FnMut(T) -> Option<NullableResult<U, E>>,
627    {
628        TryFilterMap { inner: self, f }
629    }
630}
631
632impl<I, T, E> IterExt<T, E> for I where I: Iterator<Item = NullableResult<T, E>> {}
633
634type FilterNulls<I, T, E> =
635    FilterMap<I, fn(NullableResult<T, E>) -> Option<Result<T, E>>>;
636
637/// See [IterExt::try_filter]
638pub struct TryFilter<I, P, T, E>
639where
640    I: Iterator<Item = NullableResult<T, E>>,
641    P: FnMut(&T) -> bool,
642{
643    inner: I,
644    pred: P,
645}
646
647impl<I, P, T, E> Iterator for TryFilter<I, P, T, E>
648where
649    I: Iterator<Item = NullableResult<T, E>>,
650    P: FnMut(&T) -> bool,
651{
652    type Item = NullableResult<T, E>;
653
654    #[inline]
655    fn next(&mut self) -> Option<Self::Item> {
656        match self.inner.next() {
657            None => None,
658            Some(Null) => Some(Null),
659            Some(Err(err)) => Some(Err(err)),
660            Some(Ok(item)) if (self.pred)(&item) => Some(Ok(item)),
661            Some(Ok(_)) => self.next(),
662        }
663    }
664}
665
666impl<I, P, T, E> FusedIterator for TryFilter<I, P, T, E>
667where
668    I: FusedIterator<Item = NullableResult<T, E>>,
669    P: FnMut(&T) -> bool,
670{
671}
672
673/// See [IterExt::try_filter_map]
674pub struct TryFilterMap<I, F, T, U, E>
675where
676    I: Iterator<Item = NullableResult<T, E>>,
677    F: FnMut(T) -> Option<NullableResult<U, E>>,
678{
679    inner: I,
680    f: F,
681}
682
683impl<I, F, T, U, E> Iterator for TryFilterMap<I, F, T, U, E>
684where
685    I: Iterator<Item = NullableResult<T, E>>,
686    F: FnMut(T) -> Option<NullableResult<U, E>>,
687{
688    type Item = NullableResult<U, E>;
689
690    #[inline]
691    fn next(&mut self) -> Option<Self::Item> {
692        match self.inner.next() {
693            None => None,
694            Some(Null) => Some(Null),
695            Some(Err(err)) => Some(Err(err)),
696            Some(Ok(item)) => (self.f)(item),
697        }
698    }
699}
700
701impl<I, F, T, U, E> FusedIterator for TryFilterMap<I, F, T, U, E>
702where
703    I: FusedIterator<Item = NullableResult<T, E>>,
704    F: FnMut(T) -> Option<NullableResult<U, E>>,
705{
706}
707
708/// Analogue of [TryFrom] that returns a [`NullableResult`]
709pub trait MaybeTryFrom<T>: Sized {
710    /// The type that is returned if conversion fails
711    type Error;
712
713    /// Convert a `T` to [`NullableResult<Self, Self::Error>`]
714    fn maybe_try_from(item: T) -> NullableResult<Self, Self::Error>;
715}
716
717/// Analogue of [TryInto] that returns a [`NullableResult`]
718pub trait MaybeTryInto<T>: Sized {
719    /// The type that is returned if conversion fails
720    type Error;
721
722    /// Convert a `Self` to [`NullableResult<T, Self::Error>`]
723    fn maybe_try_into(self) -> NullableResult<T, Self::Error>;
724}
725
726impl<T, U: TryFrom<T>> MaybeTryFrom<T> for U {
727    type Error = U::Error;
728
729    #[inline]
730    fn maybe_try_from(item: T) -> NullableResult<Self, Self::Error> {
731        U::try_from(item).into()
732    }
733}
734
735impl<T, U: MaybeTryFrom<T>> MaybeTryInto<U> for T {
736    type Error = U::Error;
737
738    #[inline]
739    fn maybe_try_into(self) -> NullableResult<U, Self::Error> {
740        U::maybe_try_from(self)
741    }
742}