use std;
use std::fmt;
#[allow(deprecated)]
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
use std::sync::Arc;
#[allow(deprecated)]
pub static ENABLE_DEBUG: AtomicBool = ATOMIC_BOOL_INIT;
#[macro_export]
macro_rules! errorln {
($($arg:tt)*) => { diagnostic!($crate::error::Severity::Error; $($arg)*); }
}
#[macro_export]
macro_rules! warnln {
($($arg:tt)*) => { diagnostic!($crate::error::Severity::Warning; $($arg)*) }
}
#[macro_export]
macro_rules! noteln {
($($arg:tt)*) => { diagnostic!($crate::error::Severity::Note; $($arg)*); }
}
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! debugln {
($($arg:tt)*) => {
if $crate::error::ENABLE_DEBUG.load(std::sync::atomic::Ordering::Relaxed) {
diagnostic!($crate::error::Severity::Debug; $($arg)*);
}
}
}
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! debugln {
($($arg:tt)*) => { format!($($arg)*); }
}
macro_rules! diagnostic {
($severity:expr; $($arg:tt)*) => {
eprintln!("{} {}", $severity, format!($($arg)*))
}
}
#[derive(PartialEq, Eq)]
pub enum Severity {
Debug,
Note,
Warning,
Error,
}
impl fmt::Display for Severity {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (color, prefix) = match *self {
Severity::Error => ("\x1B[31;1m", "error"),
Severity::Warning => ("\x1B[33;1m", "warning"),
Severity::Note => ("\x1B[;1m", "note"),
Severity::Debug => ("\x1B[34;1m", "debug"),
};
write!(f, "{}{}:\x1B[m", color, prefix)
}
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub struct Error {
pub msg: String,
pub cause: Option<Arc<dyn std::error::Error + Send + Sync>>,
}
impl Error {
pub fn new<S: Into<String>>(msg: S) -> Error {
Error {
msg: msg.into(),
cause: None,
}
}
pub fn chain<S, E>(msg: S, cause: E) -> Error
where
S: Into<String>,
E: std::error::Error + Send + Sync + 'static,
{
Error {
msg: msg.into(),
cause: Some(Arc::new(cause)),
}
}
}
impl std::error::Error for Error {
fn description(&self) -> &str {
&self.msg
}
fn cause(&self) -> Option<&dyn std::error::Error> {
match self.cause {
Some(ref b) => Some(b.as_ref()),
None => None,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.msg)?;
if let Some(ref c) = self.cause {
write!(f, " {}", c)?
}
Ok(())
}
}
impl From<Error> for String {
fn from(err: Error) -> String {
format!("{}", err)
}
}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Error {
Error::chain("Cannot startup runtime.".to_string(), err)
}
}
#[macro_export]
macro_rules! stageln {
($stage:expr, $($arg:tt)*) => {
$crate::error::println_stage($stage, &format!($($arg)*))
}
}
pub fn println_stage(stage: &str, message: &str) {
eprintln!("\x1B[32;1m{:>12}\x1B[0m {}", stage, message);
}