#[derive(Debug, Eq, PartialEq)] pub(crate) enum PartialResult { Ok(T), Partial(T, E), Err(E), } impl PartialResult { #[cfg(test)] pub(crate) fn err(self) -> Option { match self { PartialResult::Ok(_) => None, PartialResult::Partial(_, error) | PartialResult::Err(error) => Some(error), } } pub(crate) fn map(self, f: F) -> PartialResult where F: FnOnce(T) -> U, { match self { PartialResult::Ok(value) => PartialResult::Ok(f(value)), PartialResult::Partial(value, error) => PartialResult::Partial(f(value), error), PartialResult::Err(error) => PartialResult::Err(error), } } pub(crate) fn ok(self) -> Option { match self { PartialResult::Ok(value) | PartialResult::Partial(value, _) => Some(value), PartialResult::Err(_) => None, } } } impl PartialResult { #[cfg(test)] #[track_caller] pub(crate) fn unwrap(self) -> T { match self { PartialResult::Ok(value) => value, PartialResult::Partial(_, error) => panic!( "called `PartialResult::unwrap()` on a `Partial` value: {:?}", &error ), PartialResult::Err(error) => panic!( "called `PartialResult::unwrap()` on an `Err` value: {:?}", &error ), } } pub(crate) fn unwrap_tuple(self) -> (T, Option) { match self { PartialResult::Ok(value) => (value, None), PartialResult::Partial(value, error) => (value, Some(error)), PartialResult::Err(error) => panic!( "called `PartialResult::unwrap_tuple()` on an `Err` value: {:?}", &error ), } } } #[cfg(test)] mod tests { use super::*; #[derive(Debug, Eq, PartialEq)] struct Pass; #[derive(Debug, Eq, PartialEq)] struct Error; #[test] #[cfg_attr(coverage_nightly, coverage(off))] fn err() { assert_eq!(PartialResult::<_, Error>::Ok(Pass).err(), None); assert_eq!(PartialResult::Partial(Pass, Error).err(), Some(Error)); assert_eq!(PartialResult::::Err(Error).err(), Some(Error)); } #[test] #[cfg_attr(coverage_nightly, coverage(off))] fn map() { assert_eq!( PartialResult::<_, Error>::Ok(()).map(|()| Pass), PartialResult::Ok(Pass) ); assert_eq!( PartialResult::Partial((), Error).map(|()| Pass), PartialResult::Partial(Pass, Error) ); assert_eq!( PartialResult::<(), _>::Err(Error).map(|()| Pass), PartialResult::Err(Error) ); } #[test] #[cfg_attr(coverage_nightly, coverage(off))] fn ok() { assert_eq!(PartialResult::<_, Error>::Ok(Pass).ok(), Some(Pass)); assert_eq!(PartialResult::Partial(Pass, Error).ok(), Some(Pass)); assert_eq!(PartialResult::::Err(Error).ok(), None); } #[test] fn unwrap() { assert_eq!(PartialResult::<_, Error>::Ok(Pass).unwrap(), Pass); } #[test] #[cfg_attr(coverage_nightly, coverage(off))] #[should_panic(expected = "called `PartialResult::unwrap()` on an `Err` value")] fn unwrap_err() { PartialResult::::Err(Error).unwrap(); } #[test] #[cfg_attr(coverage_nightly, coverage(off))] #[should_panic(expected = "called `PartialResult::unwrap()` on a `Partial` value")] fn unwrap_partial() { PartialResult::Partial(Pass, Error).unwrap(); } #[test] #[cfg_attr(coverage_nightly, coverage(off))] fn unwrap_tuple() { assert_eq!( PartialResult::<_, Error>::Ok(Pass).unwrap_tuple(), (Pass, None) ); assert_eq!( PartialResult::Partial(Pass, Error).unwrap_tuple(), (Pass, Some(Error)) ); } #[test] #[cfg_attr(coverage_nightly, coverage(off))] #[should_panic(expected = "called `PartialResult::unwrap_tuple()` on an `Err` value")] fn unwrap_tuple_err() { PartialResult::::Err(Error).unwrap_tuple(); } }