devela/code/result/opt_res/ext_result.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
// devela::code::result::ext
//
//!
//
/// Marker trait to prevent downstream implementations of the [`ExtResult`] trait.
trait Sealed {}
impl<T, E> Sealed for Result<T, E> {}
/// Extension trait providing additional methods for [`Result`].
///
/// This trait is sealed and cannot be implemented for any other type.
///
/// See also [`ExtOption`][crate::ExtOption].
///
/// Based on work from:
/// - <https://github.com/rust-lang/rust/issues/62358> (contains).
#[cfg_attr(feature = "nightly_doc", doc(notable_trait))]
#[expect(private_bounds, reason = "Sealed")]
pub trait ExtResult<T, E>: Sealed {
/// Returns `true` if the result is an [`Ok`] value containing the given value.
///
/// # Examples
/// ```
/// # use devela::ExtResult;
/// assert_eq!(Ok::<_, ()>(1).contains(&1), true);
/// assert_eq!(Ok::<_, ()>(1).contains(&2), false);
/// assert_eq!(Err::<u8, _>("err").contains(&1), false);
/// ```
#[must_use]
fn contains<U: PartialEq<T>>(&self, x: &U) -> bool;
/// Returns `true` if the result is an [`Err`] value containing the given value.
///
/// # Examples
/// ```
/// # use devela::ExtResult;
/// assert_eq!(Ok::<_, &str>(1).contains_err(&"Some error message"), false);
/// assert_eq!(Err::<u8, _>("err").contains_err(&"err"), true);
/// assert_eq!(Err::<u8, _>("err2").contains_err(&"err"), false);
/// ```
#[must_use]
fn contains_err<F: PartialEq<E>>(&self, f: &F) -> bool;
// WIP
// /// Merges `self` with another `Result`.
// ///
// /// Returns
// /// - `Ok(f(l, r))` if both options are `Ok(_)`.
// /// - `Err((le, re))` if any or both options are `Err(_)`.
// ///
// /// # Examples
// /// ```
// /// # use devela::ExtOption;
// /// # use core::{cmp::min, ops::Add};
// /// let x = Some(2);
// /// let y = Some(4);
// ///
// /// assert_eq!(x.reduce(y, Add::add), Some(6));
// /// assert_eq!(x.reduce(y, min), Some(2));
// ///
// /// assert_eq!(x.reduce(None, Add::add), x);
// /// assert_eq!(None.reduce(y, min), y);
// ///
// /// assert_eq!(None.reduce(None, i32::add), None);
// /// ```
// fn reduce<F: FnOnce(T, T) -> T>(self, other: Result<T, E>, f: F) -> Result<T, E>;
}
impl<T, E> ExtResult<T, E> for Result<T, E> {
fn contains<U: PartialEq<T>>(&self, x: &U) -> bool {
self.as_ref().is_ok_and(|y| x == y)
}
fn contains_err<F: PartialEq<E>>(&self, f: &F) -> bool {
self.as_ref().err().is_some_and(|e| f == e)
}
// // WIP
// fn reduce<F: FnOnce(T, T) -> T>(self, other: Result<T, E>, f: F) -> Result<T, E> {
// match (self, other) {
// (Some(l), Some(r)) => Some(f(l, r)),
// (x @ Some(_), None) | (None, x @ Some(_)) => x,
// (None, None) => None,
// }
// }
}