#[derive(Debug)]
pub enum LogType {
Log,
Warning,
Inconvenience,
Failure,
Fatal,
Result,
}
pub struct Log<'a> {
pub log_type: LogType,
pub origin: &'a str,
pub message: &'a str,
pub allowed_responses: &'a [ErrorResponse],
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum ErrorResponse {
Retry,
Panic,
Crash,
AskUser,
}
impl ErrorResponse {
#[inline]
pub fn allowed_in(&self, log: &Log) -> bool {
log.allowed_responses.contains(self)
}
}
impl<'a> Log<'a> {
pub fn new(log_type: LogType, origin: &'a str, message: &'a str, allowed_responses: &'a [ErrorResponse]) -> Self {
Self {
log_type,
origin,
message,
allowed_responses,
}
}
}
#[macro_export]
macro_rules! log {
(($logger:ident) $origin:ident$tokens:tt) => {
$logger.verbose(
Log::new(LogType::Log, stringify!($origin), &format!$tokens, &[])
);
};
(($logger:ident) $origin:ident$tokens:tt as $type:ident) => {
$logger.verbose(
Log::new(LogType::$type, stringify!($origin), &format!$tokens, &[])
);
};
(($logger:ident.$func:ident) $origin:ident$tokens:tt as $type:ident) => {
$logger.$func(
Log::new(LogType::$type, stringify!($origin), &format!$tokens, &[])
);
};
}
#[macro_export]
macro_rules! if_err {
(($logger:ident) [$origin:ident, $err:ident => $msg:tt] retry $code:expr) => {
loop { match $code {
Ok(x) => break x,
Err($err) => match $logger.error(
Log::new(LogType::Failure, stringify!($origin), &format!$msg, &[ErrorResponse::Retry, ErrorResponse::Crash, ErrorResponse::Panic]),
) {
ErrorResponse::Retry => continue,
ErrorResponse::Panic => panic!("unexpected error: {:#?}", $err),
ErrorResponse::Crash => {
let _ = $logger.error(Log::new(LogType::Fatal, stringify!($origin), &format!("{:#?}", $err), &[]));
$logger.crash()
},
ErrorResponse::AskUser => panic!("meta error: logger returned invalid error response"),
}
}}
};
(($logger:ident) $code:block else($err:ident) $else:block) => {
match $code {
Ok(x) => x,
Err($err) => $else,
}
};
(($logger:ident) [$origin:ident, $err:ident => $msg:tt] $code:block manual {
$($response:ident => $action:expr),* $(,)?
}) => {
match $code {
Ok(x) => x,
Err($err) => match $logger.error(
Log::new(LogType::Failure, stringify!($origin), &format!$msg, &[$(ErrorResponse::$response),*])
) {
$(ErrorResponse::$response => $action,)*
_ => panic!("meta error: logger returned invalid error response"),
}
}
};
(($logger:ident) [$origin:ident, $err:ident => $msg:tt] $code:block crash $crash:expr) => {
match $code {
Ok(x) => x,
Err($err) => match $logger.error(
Log::new(LogType::Failure, stringify!($origin), &format!$msg, &[ErrorResponse::Crash])
) {
Crash => $crash,
_ => panic!("meta error: logger returned invalid error response"),
}
}
}
}