use crate::lib::*; use std::fmt::Display; pub type Res = Result; pub fn Res(v: T) -> Res where Res: Cast, { Res::to(v) } impl Cast> for Result { fn to(v: Option) -> Self { v.ok_or_else(|| "Is None".into()) } } impl Cast> for Result { fn to(v: Result) -> Self { v.map_err(|e| { let t = type_name::(); if "String" == t { e.to_string() } else { format!("{t}: {e}") } }) } } pub trait ExplainError: Sized { fn explain_err>(self, msg: impl FnOnce() -> R) -> Res; } impl ExplainError for Option { fn explain_err>(self, msg: impl FnOnce() -> R) -> Res { self.map_or_else(|| Err([&msg().into(), ": Is None"].concat()), |s| Ok(s)) } } impl ExplainError for Result { fn explain_err>(self, msg: impl FnOnce() -> R) -> Res { self.map_err(|e| [msg().into(), format!(":\n{e}")].concat()) } } pub trait UniformUnwrap: Sized { fn uni_is_err(&self) -> bool; fn uni_or_else(self, op: impl FnOnce(&str) -> T) -> T; fn fail(self) -> T { self.uni_or_else(|e| ERROR!(e)) } fn sink(self); } impl UniformUnwrap for Option { fn uni_is_err(&self) -> bool { self.is_none() } fn uni_or_else(self, op: impl FnOnce(&str) -> T) -> T { self.unwrap_or_else(|| op("Is None")) } fn sink(self) { let _ = self; } } impl UniformUnwrap for Result { fn uni_is_err(&self) -> bool { self.is_err() } fn uni_or_else(self, op: impl FnOnce(&str) -> T) -> T { self.unwrap_or_else(|e| op(&e.to_string())) } fn sink(self) { let _ = self; } } pub trait UniformUnwrapOrDefault: UniformUnwrap { fn uni_err(self) -> (T, String); fn warn(self) -> T; } impl UniformUnwrapOrDefault for Option { fn uni_err(self) -> (T, String) { (T::default(), "Is None".into()) } fn warn(self) -> T { self.unwrap_or_else(|| { FAIL!("Is None"); T::default() }) } } impl UniformUnwrapOrDefault for Result { fn uni_err(self) -> (T, String) { (T::default(), self.err().valid().to_string()) } fn warn(self) -> T { self.map_err(|e| FAIL!(e)).unwrap_or_default() } }