diff --git a/Cargo.lock b/Cargo.lock index fd6b105..451416e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -284,6 +284,15 @@ dependencies = [ "slab", ] +[[package]] +name = "generational-arena" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d3b771574f62d0548cee0ad9057857e9fc25d7a3335f140c84f6acd0bf601" +dependencies = [ + "cfg-if", +] + [[package]] name = "gimli" version = "0.22.0" @@ -383,6 +392,7 @@ dependencies = [ "chrono", "config_struct", "futures", + "generational-arena", "lazy_static", "libc", "notify", diff --git a/Cargo.toml b/Cargo.toml index 8eb4993..a0803da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,7 @@ recolored = "1.9.3" chrono = "0.4" libc = "0.2" cfg-if = "0.1" +generational-arena = "0.2" [build-dependencies] rustc_version = "0.2" diff --git a/build/config.toml b/build/config.toml index 1072f1d..3bafe14 100644 --- a/build/config.toml +++ b/build/config.toml @@ -6,3 +6,4 @@ timeout = 5 # Logging options [log] default_time_local = false +date_format = "%Y-%m-%d %H:%M:%S %Z" \ No newline at end of file diff --git a/src/config/mod.rs b/src/config/mod.rs index c663352..479855b 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -59,6 +59,7 @@ pub mod build pub use super::*; pub const DEFAULT_LOCAL_TIME: bool = CONFIG.log.default_time_local; + pub const DATE_FORMAT: std::borrow::Cow<'static, str> = CONFIG.log.date_format; } /// Print the status of `build.toml` vars diff --git a/src/hot.rs b/src/hot.rs index 7225b8d..d7f92b8 100644 --- a/src/hot.rs +++ b/src/hot.rs @@ -63,7 +63,7 @@ pub type Event = event::EventKind; /// Max event backlog (not used if `unlimited_watcher` is set) const GLOBAL_BACKLOG: usize = config::build::hot::BACKLOG; //100; /// Timeout for hook dispatches in seconds. Only set if `watcher_timeout` feature is enabled. -const GLOBAL_TIMEOUT: u64 = config::build::hot::TIMEOUT; +const GLOBAL_TIMEOUT: u64 = config::build::hot::TIMEOUT; //5 /// Decontruct a notify event into event kind and full paths. #[inline] @@ -178,7 +178,7 @@ impl Hook { /// A hook container for `Oneesan` #[derive(Debug, Clone)] -pub struct HookContainer(Arc>>); +pub struct HookContainer(Arc>>); //TODO: Change to Arena impl HookContainer { diff --git a/src/log.rs b/src/log.rs deleted file mode 100644 index 47fd997..0000000 --- a/src/log.rs +++ /dev/null @@ -1,519 +0,0 @@ -//! Global logging state -use super::util::*; - -use std::{ - fmt::{ - self, - Display, - }, - io::{ - self, - Write, - }, - borrow::Borrow, - sync::{RwLock}, -}; -use once_cell::sync::OnceCell; - -/// Print local time by default -const DEFAULT_USE_LOCAL_TIME: bool = crate::config::build::log::DEFAULT_LOCAL_TIME; - -/// Logging level -#[derive(PartialEq,Copy,Eq,Debug,Clone,Hash,Ord,PartialOrd)] -pub enum Level -{ - Silent, - Error, - Warn, - Info, - Debug, -} - -/// Contains backtrace info from where the log macro was invoked -#[derive(Debug)] -pub struct Trace -{ - line: Option, - file: Option<&'static str>, - column: Option, - - display: Opaque>>, -} - -impl Clone for Trace -{ - #[inline] - fn clone(&self) -> Self - { - Self { - line: self.line.clone(), - file: self.file.clone(), - column: self.column.clone(), - - display: Opaque::new(RwLock::new(None)), - } - } -} - -impl std::hash::Hash for Trace -{ - fn hash(&self, state: &mut H) - { - self.line.hash(state); - self.file.hash(state); - self.column.hash(state); - } -} - -impl std::cmp::PartialEq for Trace -{ - fn eq(&self, other: &Self)->bool - { - self.line == other.line && - self.file == other.file && - self.column == other.column - } -} - -impl Trace -{ - /// Create a new `Trace` manually. Generally not desireable, use `get_trace!()` instead. - pub fn new(file: Option<&'static str>, line: Option, column: Option) -> Self - { - use std::convert::TryInto; - let this = Self{ - file, - line: line.and_then(|x| x.try_into().ok()), - column: column.and_then(|x| x.try_into().ok()), - display: Opaque::new(RwLock::new(None)), - }; - this - } - - fn genstring(&self) -> Result - { - let mut out = String::new(); - use std::fmt::Write as FmtWrite; - - write!(out, "{}", self.file.unwrap_or("(unbound)"))?; - if let Some(line) = self.line { - write!(&mut out, ":{}", line)?; - } else { - write!(&mut out, ":?")?; - } - if let Some(column) = self.column { - write!(&mut out, ":{}", column)?; - } else { - write!(&mut out, ":?")?; - } - - Ok(out) - } -} - -impl std::fmt::Display for Trace -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - { - let read = self.display.read().expect("Poisoned"); - if let Some(opt) = read.as_ref() - { - write!(f, "{}", opt)?; - return Ok(()); - } - } - - let out = self.genstring()?; - - write!(f, "{}", out)?; - - let mut write = self.display.write().expect("Poisoned"); - *write = Some(out); - Ok(()) - } -} - - -impl Default for Trace -{ - #[inline] - fn default() -> Self - { - Self{ - line:None, - file:None, - column:None, - - display: Opaque::new(RwLock::new(None)), - } - } -} - -/// Get a source code trace of the current file, line and column. -#[macro_export] macro_rules! get_trace -{ - () => { - $crate::log::Trace::new(Some(file!()), Some(line!()), Some(column!())) - } -} - - -/// Append this trait to allow you to -pub trait AsLevel: fmt::Display + Borrow{ - /// Used for derived levels - fn prefix(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - write!(f, "{}/", Borrow::::borrow(self)) - } -} - -impl AsLevel for Level{ - #[inline] fn prefix(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result{Ok(())} -} -impl AsLevel for &Level{ - #[inline] fn prefix(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result{Ok(())} -} - -impl Default for Level -{ - #[inline] - fn default() -> Level - { - #[cfg(debug_assertions)] - return Level::Debug; - #[cfg(not(debug_assertions))] - return Level::Warn; - } -} - -impl std::fmt::Display for Level -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - use recolored::Colorize; - write!(f, "{}", match &self { - Self::Silent => "Fatal".bright_red().bold(), - Self::Error => "Error".red(), - Self::Warn => "Warning".yellow(), - Self::Info => "Info".normal(), - Self::Debug => "Debug".dimmed(), - }) - } -} - - -/// A logger that prints to stdout and stderr idk. -/// # TODO -/// Make this a trait and have variants that print to files and such -#[derive(Debug)] -pub struct Logger -{ - level: Level, - title: String, - use_local_time: bool, -} - -static INSTANCE: OnceCell = OnceCell::new(); - -impl Logger -{ - pub fn new(level: Level) -> Self - { - Self { - level, - title: String::new(), - use_local_time: DEFAULT_USE_LOCAL_TIME, - } - } - - #[inline] - pub fn global() -> &'static Logger - { - INSTANCE.get().expect("[logger] uninitialised") - } - - - fn initialise(level: Level) -> &'static Logger - { - INSTANCE.set(Logger::new(level)).expect("[logger] already initialised"); - Logger::global() - } - - pub fn println(&self, mut to: W, level: L, what: D, trace: T) -> io::Result<()> - where W: Write, - L: AsLevel, - D: Display, - T: Borrow - { - //lol - enum Date { - Local(chrono::DateTime), - Utc(chrono::DateTime), - } - impl std::fmt::Display for Date - { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - match self { - Self::Local(l) => write!(f, "{}", l.format("%Y-%m-%d %H:%M:%S %Z")), - Self::Utc(l) => write!(f, "{}", l.format("%Y-%m-%d %H:%M:%S %Z")), - } - } - } - impl From> for Date - { - #[inline] - fn from(from: chrono::DateTime) -> Self - { - Self::Local(from) - } - } - - impl From> for Date - { - #[inline] - fn from(from: chrono::DateTime) -> Self - { - Self::Utc(from) - } - } - - - if &self.level >= level.borrow() { - let now: Date = if self.use_local_time { - chrono::offset::Local::now().into() - } else { - chrono::offset::Utc::now().into() - }; - - write!(to, "{} ", now)?; - if self.title.len() > 0 { - write!(to, " <{}>\t", self.title)?; - } else { - write!(to, " <{}>\t", trace.borrow())?; - } - write!(to," [")?; - - struct Prefix<'a,L: AsLevel>(&'a L); - - impl<'a,L: AsLevel> std::fmt::Display for Prefix<'a, L> - { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - self.0.prefix(f) - } - } - - write!(to, "{}", Prefix(&level))?; //what a mess... - write!(to, "{}", level)?; - write!(to, "]: ")?; - writeln!(to, "{}", what)?; - } - Ok(()) - } -} -#[cfg(any(debug_assertions,feature="debug_logger"))] -#[macro_export] macro_rules! debug { - ($obj:expr) => { - { - let stdout = std::io::stdout(); - let stdout = stdout.lock(); - $crate::log::Logger::global().println(stdout, $crate::log::Level::Debug, $obj, get_trace!()).expect("i/o error"); - } - }; - ($fmt:literal, $($args:expr),*) => { - debug!(format!($fmt, $($args,)*)); - }; -} - -#[cfg(not(any(debug_assertions,feature="debug_logger")))] -#[macro_export] macro_rules! debug { - ($obj:expr) => {{}}; - ($fmt:literal, $($args:expr),*) => {{}}; -} - - -#[cfg(any(debug_assertions,feature="debug_logger"))] -#[macro_export] macro_rules! status { - ($obj:expr) => { - { - struct Status; - use std::{ - borrow::Borrow, - fmt, - }; - impl Borrow<$crate::log::Level> for Status { - fn borrow(&self) -> &$crate::log::Level - { - &$crate::log::Level::Debug - } - } - impl fmt::Display for Status - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - use recolored::Colorize; - write!(f, "{}", "Status".blue()) - } - } - - impl $crate::log::AsLevel for Status{} - - let stdout = std::io::stdout(); - let stdout = stdout.lock(); - $crate::log::Logger::global().println(stdout, Status, $obj, $crate::get_trace!()).expect("i/o error"); - } - }; - ($fmt:literal, $($args:expr),*) => { - status!(format!($fmt, $($args,)*)); - }; -} - -#[cfg(not(any(debug_assertions,feature="debug_logger")))] -#[macro_export] macro_rules! status { - ($obj:expr) => {{}}; - ($fmt:literal, $($args:expr),*) => {{}}; -} - -#[macro_export] macro_rules! info { - ($obj:expr) => { - { - let stdout = std::io::stdout(); - let stdout = stdout.lock(); - $crate::log::Logger::global().println(stdout, $crate::log::Level::Info, $obj, $crate::get_trace!()).expect("i/o error"); - } - }; - ($fmt:literal, $($args:expr),*) => { - $crate::info!(format!($fmt, $($args,)*)); - }; -} - -#[macro_export] macro_rules! important { - ($obj:expr) => { - { - struct Important; - use std::{ - borrow::Borrow, - fmt, - }; - impl Borrow<$crate::log::Level> for Important { - fn borrow(&self) -> &$crate::log::Level - { - &$crate::log::Level::Info - } - } - impl fmt::Display for Important - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - use recolored::Colorize; - write!(f, "{}", "Important".bright_blue()) - } - } - - impl $crate::log::AsLevel for Important{} - - let stdout = std::io::stdout(); - let stdout = stdout.lock(); - $crate::log::Logger::global().println(stdout, Important, $obj, $crate::get_trace!()).expect("i/o error"); - } - }; - ($fmt:literal, $($args:expr),*) => { - $crate::important!(format!($fmt, $($args,)*)); - }; -} - - -#[macro_export] macro_rules! warn { - ($obj:expr) => { - { - let stderr = std::io::stderr(); - let stderr = stderr.lock(); - $crate::log::Logger::global().println(stderr, $crate::log::Level::Warn, $obj, $crate::get_trace!()).expect("i/o error"); - } - }; - ($fmt:literal, $($args:expr),*) => { - $crate::warn!(format!($fmt, $($args,)*)); - }; -} - - -#[macro_export] macro_rules! dangerous { - ($obj:expr) => { - { - struct Dangerous; - use std::{ - borrow::Borrow, - fmt, - }; - impl Borrow<$crate::log::Level> for Dangerous { - fn borrow(&self) -> &$crate::log::Level - { - &$crate::log::Level::Warn - } - } - impl fmt::Display for Dangerous - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - use recolored::Colorize; - write!(f, "{}", "Dangerous".bright_yellow()) - } - } - - impl $crate::log::AsLevel for Dangerous{} - - let stderr = std::io::stderr(); - let stderr = stderr.lock(); - $crate::log::Logger::global().println(stderr, Dangerous, $obj, $crate::get_trace!()).expect("i/o error"); - } - }; - ($fmt:literal, $($args:expr),*) => { - $crate::dangerous!(format!($fmt, $($args,)*)); - }; -} - -#[macro_export] macro_rules! error { - ($obj:expr) => { - { - let stderr = std::io::stderr(); - let stderr = stderr.lock(); - $crate::log::Logger::global().println(stderr, $crate::log::Level::Error, $obj, $crate::get_trace!()).expect("i/o error"); - } - }; - ($fmt:literal, $($args:expr),*) => { - $crate::error!(format!($fmt, $($args,)*)); - }; -} - -#[macro_export] macro_rules! fatal { - ($obj:expr) => { - { - let stdout = std::io::stdout(); - let stdout = stdout.lock(); - $crate::log::Logger::global().println(stdout, $crate::log::Level::Silent, $obj, $crate::get_trace!()).expect("i/o error"); - - std::process::exit(-1) - } - }; - ($fmt:literal, $($args:expr),*) => { - $crate::fatal!(format!($fmt, $($args,)*)); - }; -} - -/// Initialise the global logger instance. If logging macros are called before this, they will panic. -#[inline] -pub fn init(level: Level) -{ - Logger::initialise(level); -} - -/// The global logger's level -#[inline] -pub fn level() -> &'static Level -{ - &Logger::global().level -}