commit 0dd0715c293b3b17b50a8edf386c09f491cb0c8c Author: Jacob Babich Date: Wed Dec 27 15:38:47 2023 -0500 meta: initial commit (archival) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c6e931 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +.history/ + diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e23f3ad --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "experiment-stackable-errors" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a2644db --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "experiment-stackable-errors" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..1908ed1 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,50 @@ +use std::{ + error::Error, + fmt::{Debug, Display, Formatter}, +}; + +#[derive(Debug)] +pub struct ErrorWithSuggestion { + error: E, + suggestion: S, +} + +impl Display for ErrorWithSuggestion { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + self.error.fmt(f)?; + writeln!(f)?; + + write!(f, "💡 ")?; + self.suggestion.fmt(f)?; + + Ok(()) + } +} + +impl Error for ErrorWithSuggestion { + fn source(&self) -> Option<&(dyn Error + 'static)> { + self.error.source() + } +} + +pub trait ResultExt { + type O; + type E; + + fn with_suggestion( + self, + suggestion: Suggestion, + ) -> Result>; +} + +impl ResultExt for Result { + type O = Ok; + type E = Err; + + fn with_suggestion( + self, + suggestion: Suggestion, + ) -> Result> { + self.map_err(|error| ErrorWithSuggestion { error, suggestion }) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..66532cc --- /dev/null +++ b/src/main.rs @@ -0,0 +1,116 @@ +use std::{ + env::{self, VarError}, + fmt::{Debug, Display, Formatter}, +}; + +use experiment_stackable_errors::{ErrorWithSuggestion, ResultExt}; + +#[derive(Debug)] +struct EnsureEnvironmentVariableExists; + +impl Display for EnsureEnvironmentVariableExists { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "ensure you provide a value for this environment variable" + ) + } +} + +#[derive(Debug)] +struct EnvironmentVariableOrigin(String); + +impl Display for EnvironmentVariableOrigin { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let variable = &self.0; + write!(f, "the {variable} environment variable") + } +} + +struct PassANumber; +impl Display for PassANumber { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "pass a number, e.x. 247") + } +} + +#[derive(Debug)] +enum ArgumentError { + MissingEnvironmentVariable(ErrorWithSuggestion), +} + +impl From> for ArgumentError { + fn from(error: ErrorWithSuggestion) -> Self { + Self::MissingEnvironmentVariable(error) + } +} + +impl Display for ArgumentError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + writeln!(f, "argument error")?; + + writeln!(f, "caused by")?; + match self { + ArgumentError::MissingEnvironmentVariable(err) => Display::fmt(err, f)?, + } + + Ok(()) + } +} + +#[derive(Debug)] +enum AppError { + ArgumentError(ArgumentError), +} + +impl From for AppError { + fn from(value: ArgumentError) -> Self { + AppError::ArgumentError(value) + } +} + +impl Display for AppError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + writeln!(f, "app error")?; + + writeln!(f, "caused by")?; + match self { + AppError::ArgumentError(err) => Display::fmt(err, f)?, + } + + Ok(()) + } +} + +fn get_environment_variables() -> Result<(String,), ArgumentError> { + // TODO: with_origin + let data = env::var("DATA").with_suggestion(EnsureEnvironmentVariableExists)?; + + Ok((data,)) +} + +fn app() -> Result<(), AppError> { + let environment_variables = get_environment_variables()?; + + println!("hello {environment_variables:?}"); + + Ok(()) +} + +struct DisplayFormatter(U); + +impl Debug for DisplayFormatter { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl From for DisplayFormatter { + fn from(value: U) -> Self { + Self(value) + } +} + +fn main() -> Result<(), DisplayFormatter> { + Ok(app()?) +}