lazy_errors/or_wrap_with.rs
1use core::fmt::Display;
2
3use crate::Error;
4
5/// Adds the [`or_wrap_with`](Self::or_wrap_with) method on `Result<_, E>`,
6/// if `E` implements [`Into<I>`](crate::Error#inner-error-type-i).
7///
8/// Do not implement this trait.
9/// Importing the trait is sufficient due to blanket implementations.
10/// The trait is implemented on `Result<_, E>` if `E` implements `Into<I>`,
11/// where `I` is the [_inner error type_](crate::Error#inner-error-type-i),
12/// typically [`prelude::Stashable`].
13#[cfg_attr(
14 any(feature = "rust-v1.81", feature = "std"),
15 doc = r##"
16
17[`prelude::Stashable`]: crate::prelude::Stashable
18"##
19)]
20#[cfg_attr(
21 not(any(feature = "rust-v1.81", feature = "std")),
22 doc = r##"
23
24[`prelude::Stashable`]: crate::surrogate_error_trait::prelude::Stashable
25"##
26)]
27pub trait OrWrapWith<F, M, T, E>
28where
29 F: FnOnce() -> M,
30 M: Display,
31{
32 /// If `self` is `Result::Ok(value)`, returns `Result::Ok(value)`;
33 /// if `self` is `Result::Err(e1)`, returns `Result::Err(e2)`
34 /// where `e2` is an [`Error`] containing a [`WrappedError`]
35 /// that will hold the original `e1` value
36 /// and annotates it with the message provided by the user.
37 ///
38 /// This method behaves identically to [`or_wrap`]
39 /// except that you can pass some information
40 /// about the context of the error.
41 ///
42 /// ```
43 /// # use lazy_errors::doctest_line_num_helper as replace_line_numbers;
44 /// #[cfg(any(feature = "rust-v1.81", feature = "std"))]
45 /// use lazy_errors::prelude::*;
46 ///
47 /// #[cfg(not(any(feature = "rust-v1.81", feature = "std")))]
48 /// use lazy_errors::surrogate_error_trait::prelude::*;
49 ///
50 /// fn run(tokens: &[&str]) -> Result<(), Error> {
51 /// all_ascii(tokens).or_wrap_with(|| "Input is not ASCII")
52 /// }
53 ///
54 /// fn all_ascii(tokens: &[&str]) -> Result<(), String> {
55 /// match tokens.iter().find(|s| !s.is_ascii()) {
56 /// None => Ok(()),
57 /// Some(not_ascii) => Err(not_ascii.to_string()),
58 /// }
59 /// }
60 ///
61 /// fn main() {
62 /// assert!(run(&["foo", "bar"]).is_ok());
63 ///
64 /// let err = run(&["foo", "❌", "bar"]).unwrap_err();
65 /// let printed = format!("{err:#}");
66 /// let printed = replace_line_numbers(&printed);
67 /// assert_eq!(printed, indoc::indoc! {"
68 /// Input is not ASCII: ❌
69 /// at src/or_wrap_with.rs:1234:56"});
70 /// }
71 /// ```
72 ///
73 /// Please take a look at [`or_wrap`] if you do not want to supply
74 /// the informative message.
75 ///
76 /// [`WrappedError`]: crate::WrappedError
77 /// [`or_wrap`]: crate::OrWrap::or_wrap
78 fn or_wrap_with<I>(self, f: F) -> Result<T, Error<I>>
79 where
80 E: Into<I>;
81}
82
83impl<F, M, T, E> OrWrapWith<F, M, T, E> for Result<T, E>
84where
85 F: FnOnce() -> M,
86 M: Display,
87{
88 #[track_caller]
89 fn or_wrap_with<I>(self, f: F) -> Result<T, Error<I>>
90 where
91 E: Into<I>,
92 {
93 match self {
94 Ok(t) => Ok(t),
95 Err(inner) => Err(Error::wrap_with(inner, f())),
96 }
97 }
98}