diff --git a/src/ext.rs b/src/ext.rs new file mode 100644 index 0000000..3d6e34d --- /dev/null +++ b/src/ext.rs @@ -0,0 +1,110 @@ +//! Extensions +use super::*; + +/// Essentially equivelant bound as `eyre::StdError` (private trait) +/// +/// Useful for when using traits that convert a generic type into an `eyre::Report`. +pub trait EyreError: std::error::Error + Send + Sync + 'static{} +impl EyreError for T +where T: std::error::Error + Send + Sync + 'static{} + +pub trait IntoEyre +{ + fn into_eyre(self) -> eyre::Result; +} + +impl IntoEyre for Result +{ + #[inline(always)] + fn into_eyre(self) -> eyre::Result { + match self { + Err(e) => Err(eyre::Report::from(e)), + Ok(y) => Ok(y), + } + } +} + +pub trait FlattenReports +{ + /// Flatten a `eyre::Result>` into an `eyre::Result` + fn flatten(self) -> eyre::Result; +} + +pub trait FlattenEyreResult +where E: EyreError +{ + /// Flatten a `Result, OE>` into an `eyre::Result` + fn flatten(self) -> eyre::Result; +} + +pub trait FlattenResults +{ + /// Flatten a `Result, E>` into a `Result`. + fn flatten(self) -> Result; +} + +impl> FlattenResults for Result, E> +{ + /// Flatten a `Result>, E>` into a `Result` + /// + /// This will convert the inner error into the type of the outer error. + #[inline] + fn flatten(self) -> Result { + match self { + Err(e) => Err(e), + Ok(Ok(e)) => Ok(e), + Ok(Err(e)) => Err(e.into()) + } + } +} + +impl FlattenEyreResult for Result, E> +{ + #[inline] + fn flatten(self) -> eyre::Result { + match self { + Err(e) => Err(e).with_note(|| "Flattened report (outer)"), + Ok(Err(e)) => Err(e).with_warning(|| "Flattened report (inner)"), + Ok(Ok(a)) => Ok(a), + } + } +} + +impl FlattenReports for eyre::Result> +{ + #[inline] + fn flatten(self) -> eyre::Result { + match self { + Err(e) => Err(e.with_note(|| "Flattened report (outer)")), + Ok(Err(e)) => Err(e.with_warning(|| "Flattened report (inner)")), + Ok(Ok(a)) => Ok(a), + } + } +} + +impl FlattenReports for eyre::Result> +{ + #[inline] + fn flatten(self) -> eyre::Result { + match self { + Err(e) => Err(e.with_note(|| "Flattened report (outer)")), + Ok(None) => Err(eyre!("Value expected, but not found").with_section(|| format!("Option<{}>", std::any::type_name::()).header("Option type was")).with_warning(|| "Flattened report (inner)")), + Ok(Some(a)) => Ok(a), + } + } +} + +impl FlattenEyreResult for Result, E> +{ + #[inline] + fn flatten(self) -> eyre::Result { + match self { + Err(e) => Err(e).with_note(|| "Flattened report (outer)"), + Ok(None) => Err(eyre!("Value expected, but not found") + .with_section(|| format!("Option<{}>", std::any::type_name::()) + .header("Option type was")) + .with_warning(|| "Flattened report (inner)")), + Ok(Some(a)) => Ok(a), + } + } +} diff --git a/src/main.rs b/src/main.rs index f9c82dc..d6044ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,6 +65,7 @@ macro_rules! function { }} } +mod ext; use ext::*; mod sys; use sys::{ try_get_size, diff --git a/src/memfile/hp.rs b/src/memfile/hp.rs index a9a7e6a..9b6f53d 100644 --- a/src/memfile/hp.rs +++ b/src/memfile/hp.rs @@ -300,15 +300,12 @@ mod tests fn get_bytes<'a, P: 'a>(from: P) -> eyre::Result> +'a> where P: AsRef { + use crate::*; let dir = from.as_ref().read_dir()?; Ok(dir .map(|x| x.map(|n| n.file_name())) .map(|name| name.map(|name| super::find_size_bytes(name))) - .map(|result| match result { - Ok(None) => Err(eyre!("Failed to extract bytes")), - Ok(Some(x)) => Ok(x), - Err(err) => Err(eyre::Report::from(err)), - })) + .map(|result| result.flatten())) } #[test]