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}