meta: initial commit (archival)

This commit is contained in:
2023-12-27 15:38:47 -05:00
commit 0dd0715c29
5 changed files with 184 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/target
.history/

7
Cargo.lock generated Normal file
View File

@@ -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"

8
Cargo.toml Normal file
View File

@@ -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]

50
src/lib.rs Normal file
View File

@@ -0,0 +1,50 @@
use std::{
error::Error,
fmt::{Debug, Display, Formatter},
};
#[derive(Debug)]
pub struct ErrorWithSuggestion<E, S> {
error: E,
suggestion: S,
}
impl<E: Display, S: Display> Display for ErrorWithSuggestion<E, S> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.error.fmt(f)?;
writeln!(f)?;
write!(f, "💡 ")?;
self.suggestion.fmt(f)?;
Ok(())
}
}
impl<E: Error, S: Debug + Display> Error for ErrorWithSuggestion<E, S> {
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.error.source()
}
}
pub trait ResultExt {
type O;
type E;
fn with_suggestion<Suggestion: Display>(
self,
suggestion: Suggestion,
) -> Result<Self::O, ErrorWithSuggestion<Self::E, Suggestion>>;
}
impl<Ok, Err> ResultExt for Result<Ok, Err> {
type O = Ok;
type E = Err;
fn with_suggestion<Suggestion: Display>(
self,
suggestion: Suggestion,
) -> Result<Self::O, ErrorWithSuggestion<Self::E, Suggestion>> {
self.map_err(|error| ErrorWithSuggestion { error, suggestion })
}
}

116
src/main.rs Normal file
View File

@@ -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<VarError, EnsureEnvironmentVariableExists>),
}
impl From<ErrorWithSuggestion<VarError, EnsureEnvironmentVariableExists>> for ArgumentError {
fn from(error: ErrorWithSuggestion<VarError, EnsureEnvironmentVariableExists>) -> 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<ArgumentError> 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>(U);
impl<U: Display> Debug for DisplayFormatter<U> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl<U: Display> From<U> for DisplayFormatter<U> {
fn from(value: U) -> Self {
Self(value)
}
}
fn main() -> Result<(), DisplayFormatter<AppError>> {
Ok(app()?)
}