err_or/
lib.rs

1//! This crate adds [`err_or`] and [`err_or_else`] methods to the [`Option`]
2//! type which allow converting `Option<E>` into `Result<_, E>`.
3//!
4//! Those methods were proposed in [`rust-lang/rust#73040`](https://github.com/rust-lang/rust/pull/73040)
5//! PR, but it was closed.
6//!
7//! This crate is `#![no_std]` compatible.
8//!
9//! [`err_or`]: OptionExt::err_or
10//! [`err_or_else`]: OptionExt::err_or_else
11#![cfg_attr(not(feature = "std"), no_std)]
12#![forbid(unsafe_code)]
13#![deny(missing_docs, broken_intra_doc_links)]
14
15/// Extension trait for [`Option`].
16pub trait OptionExt {
17    /// Value type, i.e. `T` for `Option<T>`.
18    type Item;
19
20    /// Transforms the `Option<T>` into a [`Result<O, T>`], mapping [`Some(v)`]
21    /// to [`Err(v)`] and [`None`] to [`Ok(ok)`].
22    ///
23    /// Arguments passed to `err_or` are eagerly evaluated; if you are passing
24    /// the result of a function call, it is recommended to use
25    /// [`err_or_else`], which is lazily evaluated.
26    ///
27    /// [`Result<O, T>`]: core::result::Result
28    /// [`Err(v)`]: core::result::Result#variant.Err
29    /// [`Ok(ok)`]: core::result::Result#variant.Ok
30    /// [`None`]: core::option::Option#variant.None
31    /// [`Some(v)`]: core::option::Option#variant.Some
32    /// [`err_or_else`]: #tymethod.err_or_else
33    ///
34    /// # Examples
35    ///
36    /// ```
37    /// use err_or::OptionExt;
38    ///
39    /// let x = Some("foo");
40    /// assert_eq!(x.err_or(0), Err("foo"));
41    ///
42    /// let x: Option<&str> = None;
43    /// assert_eq!(x.err_or(0), Ok(0));
44    /// ```
45    fn err_or<O>(self, ok: O) -> Result<O, Self::Item>;
46
47    /// Transforms the `Option<T>` into a [`Result<O, T>`], mapping [`Some(v)`]
48    /// to [`Err(v)`] and [`None`] to [`Ok(ok())`].
49    ///
50    /// [`Result<O, T>`]: core::result::Result
51    /// [`Err(v)`]: core::result::Result#variant.Err
52    /// [`Ok(ok())`]: core::result::Result#variant.Ok
53    /// [`None`]: core::option::Option#variant.None
54    /// [`Some(v)`]: core::option::Option#variant.Some
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// use err_or::OptionExt;
60    ///
61    /// let x = Some("foo");
62    /// assert_eq!(x.err_or_else(|| 0), Err("foo"));
63    ///
64    /// let x: Option<&str> = None;
65    /// assert_eq!(x.err_or_else(|| 0), Ok(0));
66    /// ```
67    fn err_or_else<O, F>(self, ok: F) -> Result<O, Self::Item>
68    where
69        F: FnOnce() -> O;
70}
71
72impl<T> OptionExt for Option<T> {
73    type Item = T;
74
75    #[inline]
76    fn err_or<O>(self, ok: O) -> Result<O, Self::Item> {
77        match self {
78            Some(v) => Err(v),
79            None => Ok(ok),
80        }
81    }
82
83    #[inline]
84    fn err_or_else<O, F>(self, ok: F) -> Result<O, Self::Item>
85    where
86        F: FnOnce() -> O,
87    {
88        match self {
89            Some(v) => Err(v),
90            None => Ok(ok()),
91        }
92    }
93}