use std::{
collections::HashMap,
};
use crate::{
entry::{
err,
err_with,
},
types::{
Error,
Error_,
Error_2,
FullError,
},
Flag,
Log,
};
pub trait ErrContext {
fn context(self, message: impl ToString) -> Error;
fn context_with(self, message: impl ToString, attrs: impl Fn(&mut HashMap<&'static str, String>) -> ()) -> Error;
fn stack_context<F: Flag>(self, log: &Log<F>, message: impl ToString) -> Error;
fn stack_context_with<
F: Flag,
>(
self,
log: &Log<F>,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) -> Error;
}
impl<T: Into<Error>> ErrContext for T {
fn context(self, message: impl ToString) -> Error {
return Error(Box::new(Error_ {
inner: Error_2::Full(FullError {
message: message.to_string(),
attrs: HashMap::new(),
causes: vec![self.into()],
}),
incidental: vec![],
}));
}
fn context_with(
self,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) -> Error {
let mut new_attrs = HashMap::new();
attrs(&mut new_attrs);
return Error(Box::new(Error_ {
inner: Error_2::Full(FullError {
message: message.to_string(),
attrs: new_attrs,
causes: vec![self.into()],
}),
incidental: vec![],
}));
}
fn stack_context<F: Flag>(self, log: &Log<F>, message: impl ToString) -> Error {
return Error(Box::new(Error_ {
inner: Error_2::Full(FullError {
message: message.to_string(),
attrs: log.attrs.clone(),
causes: vec![self.into()],
}),
incidental: vec![],
}));
}
fn stack_context_with<
F: Flag,
>(
self,
log: &Log<F>,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) -> Error {
let mut new_attrs = log.attrs.clone();
attrs(&mut new_attrs);
return Error(Box::new(Error_ {
inner: Error_2::Full(FullError {
message: message.to_string(),
attrs: new_attrs,
causes: vec![self.into()],
}),
incidental: vec![],
}));
}
}
pub trait ResultContext<O> {
fn context(self, message: impl ToString) -> Result<O, Error>;
fn context_with(
self,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) -> Result<O, Error>;
fn stack_context<F: Flag>(self, log: &Log<F>, message: impl ToString) -> Result<O, Error>;
fn stack_context_with<
F: Flag,
>(
self,
log: &Log<F>,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) -> Result<O, Error>;
fn also<O2, E: Into<Error>>(self, r: Result<O2, E>) -> Result<O, Error>;
fn log<F: Flag>(self, log: &Log<F>, flags: F, message: impl ToString);
fn log_with<
F: Flag,
>(
self,
log: &Log<F>,
flags: F,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
);
}
impl<O, E: Into<Error>> ResultContext<O> for Result<O, E> {
fn context(self, message: impl ToString) -> Result<O, Error> {
match self {
Ok(x) => Ok(x),
Err(e) => Err(e.context(message)),
}
}
fn context_with(
self,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) -> Result<O, Error> {
match self {
Ok(x) => Ok(x),
Err(e) => Err(e.context_with(message, attrs)),
}
}
fn stack_context<F: Flag>(self, log: &Log<F>, message: impl ToString) -> Result<O, Error> {
match self {
Ok(x) => Ok(x),
Err(e) => Err(e.stack_context(log, message)),
}
}
fn stack_context_with<
F: Flag,
>(
self,
log: &Log<F>,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) -> Result<O, Error> {
match self {
Ok(x) => Ok(x),
Err(e) => Err(e.stack_context_with(log, message, attrs)),
}
}
fn also<O2, E2: Into<Error>>(self, r: Result<O2, E2>) -> Result<O, Error> {
match self {
Ok(o) => match r {
Ok(_) => {
return Ok(o);
},
Err(e2) => {
return Err(e2.into());
},
},
Err(e) => match r {
Ok(_) => return Err(e.into()),
Err(e2) => return Err(e.into().also(e2.into())),
},
}
}
fn log<F: Flag>(self, log: &Log<F>, flags: F, message: impl ToString) {
if let Err(e) = self.context(message) {
log.log_err(flags, e);
}
}
fn log_with<
F: Flag,
>(
self,
log: &Log<F>,
flags: F,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) {
if let Err(e) = self.context_with(message, attrs) {
log.log_err(flags, e);
}
}
}
impl<O> ResultContext<O> for Option<O> {
fn context(self, message: impl ToString) -> Result<O, Error> {
match self {
Some(x) => Ok(x),
None => Err(err(message)),
}
}
fn context_with(
self,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) -> Result<O, Error> {
match self {
Some(x) => Ok(x),
None => Err(err_with(message, attrs)),
}
}
fn stack_context<F: Flag>(self, log: &Log<F>, message: impl ToString) -> Result<O, Error> {
match self {
Some(x) => Ok(x),
None => Err(log.err(message)),
}
}
fn stack_context_with<
F: Flag,
>(
self,
log: &Log<F>,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) -> Result<O, Error> {
match self {
Some(x) => Ok(x),
None => Err(log.err_with(message, attrs)),
}
}
fn also<O2, E2: Into<Error>>(self, r: Result<O2, E2>) -> Result<O, Error> {
match self {
Some(o) => match r {
Ok(_) => {
return Ok(o);
},
Err(e2) => {
return Err(e2.into());
},
},
None => match r {
Ok(_) => return Err(err("No value")),
Err(e2) => return Err(err("No value").also(e2.into())),
},
}
}
fn log<F: Flag>(self, log: &Log<F>, flags: F, message: impl ToString) {
if self.is_none() {
log.log_err(flags, err("No value").context(message));
}
}
fn log_with<
F: Flag,
>(
self,
log: &Log<F>,
flags: F,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) {
if self.is_none() {
log.log_err(flags, err("No value").context_with(message, attrs));
}
}
}