#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))] #![feature(try_trait_v2)] /// [Probably] is a better [Option]: /// - [Something] is like [Some] /// - [Nothing] is like [None] #[derive(is_macro::Is, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, Hash, Default)] pub enum Probably { /// No value. #[default] Nothing, /// Some value of type `T`. Something(T), } pub use Probably::{Nothing, Something}; impl std::process::Termination for Probably { fn report(self) -> std::process::ExitCode { match self { Nothing => std::process::ExitCode::FAILURE, _ => std::process::ExitCode::SUCCESS, } } } impl std::ops::FromResidual for Probably { fn from_residual(residual: Probably) -> Self { match residual { Nothing => Nothing, Something(_) => todo!(), } } } impl std::ops::Try for Probably { type Output = T; type Residual = Probably; fn from_output(output: Self::Output) -> Self { Something(output) } fn branch(self) -> std::ops::ControlFlow { match self { Something(v) => std::ops::ControlFlow::Continue(v), Nothing => std::ops::ControlFlow::Break(Nothing), } } } impl From for Probably { fn from(x: T) -> Self { Something(x) } } impl From> for Probably { fn from(x: Option) -> Self { match x { Some(v) => Something(v), None => Nothing, } } } impl Into> for Probably { fn into(self) -> Option { match self { Something(x) => Some(x), Nothing => None, } } } impl Probably> { /// Converts from `Probably>` to `Probably`. /// /// # Examples /// /// Basic usage: /// /// ``` /// let x: Probably> = Something(Something(6)); /// assert_eq!(Something(6), x.flatten()); /// /// let x: Probably> = Something(Nothing); /// assert_eq!(Nothing, x.flatten()); /// /// let x: Probably> = Nothing; /// assert_eq!(Nothing, x.flatten()); /// ``` /// /// /// Flattening only removes one level of nesting at a time: /// /// ``` /// let x: Probably>> = Something(Something(Something(6))); /// assert_eq!(Something(Something(6)), x.flatten()); /// assert_eq!(Something(6), x.flatten().flatten()); /// ``` pub fn flatten(self) -> Probably { match self { Something(inner) => inner, Nothing => Nothing, } } } #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { let result = 2 + 2; assert_eq!(result, 4); } #[test] fn from_option_works() { let some = Some(42u8); let sth: Probably = some.into(); assert_eq!(sth, Something(42u8)); } #[test] fn from_unit_works() { let unit = (); let sth: Probably<()> = unit.into(); assert_eq!(sth, Something(())); } #[test] fn from_some_works() { let unit = Some(()); let sth: Probably<()> = unit.into(); assert_eq!(sth, Something(())); } }