1#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
2
3#![feature(try_trait_v2)]
4
5#[derive(is_macro::Is, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, Hash, Default)]
9pub enum Probably<T> {
10 #[default]
12 Nothing,
13 Something(T),
15}
16
17pub use Probably::{Nothing, Something};
18
19impl<T> std::process::Termination for Probably<T> {
20 fn report(self) -> std::process::ExitCode {
21 match self {
22 Nothing => std::process::ExitCode::FAILURE,
23 _ => std::process::ExitCode::SUCCESS,
24 }
25 }
26}
27
28impl<T> std::ops::FromResidual for Probably<T> {
29 fn from_residual(residual: Probably<std::convert::Infallible>) -> Self {
30 match residual {
31 Nothing => Nothing,
32 Something(_) => todo!(),
33 }
34 }
35}
36
37impl<T> std::ops::Try for Probably<T> {
38 type Output = T;
39 type Residual = Probably<std::convert::Infallible>;
40
41 fn from_output(output: Self::Output) -> Self {
42 Something(output)
43 }
44
45 fn branch(self) -> std::ops::ControlFlow<Self::Residual, Self::Output> {
46 match self {
47 Something(v) => std::ops::ControlFlow::Continue(v),
48 Nothing => std::ops::ControlFlow::Break(Nothing),
49 }
50 }
51}
52
53impl<T> From<T> for Probably<T> {
54 fn from(x: T) -> Self {
55 Something(x)
56 }
57}
58
59impl<T> From<Option<T>> for Probably<T> {
60 fn from(x: Option<T>) -> Self {
61 match x {
62 Some(v) => Something(v),
63 None => Nothing,
64 }
65 }
66}
67
68impl<T> Into<Option<T>> for Probably<T> {
69 fn into(self) -> Option<T> {
70 match self {
71 Something(x) => Some(x),
72 Nothing => None,
73 }
74 }
75}
76
77impl<T> Probably<Probably<T>> {
78 pub fn flatten(self) -> Probably<T> {
104 match self {
105 Something(inner) => inner,
106 Nothing => Nothing,
107 }
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn it_works() {
117 let result = 2 + 2;
118 assert_eq!(result, 4);
119 }
120
121 #[test]
122 fn from_option_works() {
123 let some = Some(42u8);
124 let sth: Probably<u8> = some.into();
125 assert_eq!(sth, Something(42u8));
126 }
127
128 #[test]
129 fn from_unit_works() {
130 let unit = ();
131 let sth: Probably<()> = unit.into();
132 assert_eq!(sth, Something(()));
133 }
134
135 #[test]
136 fn from_some_works() {
137 let unit = Some(());
138 let sth: Probably<()> = unit.into();
139 assert_eq!(sth, Something(()));
140 }
141}