use crate::prelude::*;
pub type YRes<T> = Result<T, YError>;
pub const INTERNAL_ERROR: &str = "INTERNAL_ERROR";
#[derive(Debug, Clone)]
pub struct YError {
pub code: String,
pub msg: String,
pub module: String,
pub file: String,
pub line: u32,
pub trace: Vec<String>,
}
impl YError {
pub fn upgrade(mut self, err: YError) -> Self {
self.code = err.code;
self.msg = err.msg;
self
}
pub fn code(mut self, code: &str) -> Self {
self.code = code.to_string();
self
}
pub fn msg(mut self, msg: &str) -> Self {
self.msg = msg.to_string();
self
}
pub fn trace(mut self, ctx: String) -> Self {
self.trace.push(ctx);
self
}
pub fn is_internal(&self) -> bool {
self.code == INTERNAL_ERROR
}
}
impl From<diesel::result::Error> for YError {
fn from(err: diesel::result::Error) -> YError {
err!("got diesel::result::Error").trace(ctx!("YError::From<diesel::result::Error>", err))
}
}
pub trait Trace {
fn upgrade(self, err: YError) -> Self;
fn code(self, code: &str) -> Self;
fn msg(self, msg: &str) -> Self;
fn trace(self, ctx: String) -> Self;
}
impl<T> Trace for YRes<T> {
fn upgrade(mut self, new_err: YError) -> Self {
if let Err(err) = &mut self {
err.code = new_err.code;
err.msg = new_err.msg;
}
self
}
fn code(mut self, code: &str) -> Self {
if let Err(err) = &mut self {
err.code = code.to_string();
}
self
}
fn msg(mut self, msg: &str) -> Self {
if let Err(err) = &mut self {
err.msg = msg.to_string();
}
self
}
fn trace(mut self, ctx: String) -> Self {
if let Err(err) = &mut self {
err.trace.push(ctx)
}
self
}
}
#[macro_export]
macro_rules! ctx {
() => {
format!("MODULE={}, FILE={}, LINE={}", module_path!(), file!(), line!())
};
($process:literal) => {
format!("{}, MODULE={}, FILE={}, LINE={}", $process, module_path!(), file!(), line!())
};
($process:literal, $($value:expr),*) => {{
let mut ctx = format!("{}, ", $process);
$(
let var_trace = format!("{}={:?}, ", stringify!($value), $value);
ctx.push_str(&var_trace);
)*
ctx.push_str(&format!("MODULE={}, FILE={}, LINE={}", module_path!(), file!(), line!()));
ctx
}};
($($value:expr),*) => {{
let mut ctx = String::new();
$(
let var_trace = format!("{}={:?}, ", stringify!($value), $value);
ctx.push_str(&var_trace);
)*
ctx.push_str(&format!("MODULE={}, FILE={}, LINE={}", module_path!(), file!(), line!()));
ctx
}};
}
#[macro_export]
macro_rules! err {
() => {
YError {
code: INTERNAL_ERROR.to_string(),
msg: "".to_string(),
module: module_path!().to_string(),
file: file!().to_string(),
line: line!(),
trace: vec![],
}
};
($msg:literal) => {
YError {
code: INTERNAL_ERROR.to_string(),
msg: $msg.to_string(),
module: module_path!().to_string(),
file: file!().to_string(),
line: line!(),
trace: vec![],
}
};
($msg:literal, $($arg:tt)*) => {
YError {
code: INTERNAL_ERROR.to_string(),
msg: format!($msg, $($arg)*),
module: module_path!().to_string(),
file: file!().to_string(),
line: line!(),
trace: vec![],
}
};
($code:literal:$msg:literal) => {
YError {
code: $code.to_string(),
msg: $msg.to_string(),
module: module_path!().to_string(),
file: file!().to_string(),
line: line!(),
trace: vec![],
}
};
($code:literal:$msg:literal, $($arg:tt)*) => {
YError {
code: $code.to_string(),
msg: format!($msg, $($arg)*),
module: module_path!().to_string(),
file: file!().to_string(),
line: line!(),
trace: vec![],
}
};
}