use std::{
collections::HashMap,
};
use crate::{
entry::{
err,
err_with,
},
types::{
Error,
Error_,
},
Level,
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(self, log: &Log, message: impl ToString) -> Error;
fn stack_context_with(
self,
log: &Log,
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_ {
message: message.to_string(),
attrs: HashMap::new(),
context: vec![],
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_ {
message: message.to_string(),
attrs: new_attrs,
context: vec![],
causes: vec![self.into()],
incidental: vec![],
}));
}
fn stack_context(self, log: &Log, message: impl ToString) -> Error {
return Error(Box::new(Error_ {
message: message.to_string(),
attrs: HashMap::new(),
context: vec![log.clone()],
causes: vec![self.into()],
incidental: vec![],
}));
}
fn stack_context_with(
self,
log: &Log,
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_ {
message: message.to_string(),
attrs: new_attrs,
context: vec![log.clone()],
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(self, log: &Log, message: impl ToString) -> Result<O, Error>;
fn stack_context_with(
self,
log: &Log,
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(self, log: &Log, level: Level, message: impl ToString);
fn log_with(
self,
log: &Log,
level: Level,
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(self, log: &Log, message: impl ToString) -> Result<O, Error> {
match self {
Ok(x) => Ok(x),
Err(e) => Err(e.stack_context(log, message)),
}
}
fn stack_context_with(
self,
log: &Log,
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(self, log: &Log, level: Level, message: impl ToString) {
if let Err(e) = self.context(message) {
log.log_err(level, e);
}
}
fn log_with(
self,
log: &Log,
level: Level,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) {
if let Err(e) = self.context_with(message, attrs) {
log.log_err(level, 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(self, log: &Log, message: impl ToString) -> Result<O, Error> {
match self {
Some(x) => Ok(x),
None => Err(log.err(message)),
}
}
fn stack_context_with(
self,
log: &Log,
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(self, log: &Log, level: Level, message: impl ToString) {
if self.is_none() {
log.log_err(level, err("No value").context(message));
}
}
fn log_with(
self,
log: &Log,
level: Level,
message: impl ToString,
attrs: impl Fn(&mut HashMap<&'static str, String>) -> (),
) {
if self.is_none() {
log.log_err(level, err("No value").context_with(message, attrs));
}
}
}
pub trait ResultIgnore {
fn ignore(self);
}
impl<T, E> ResultIgnore for Result<T, E> {
fn ignore(self) {
_ = self;
}
}