use log::Level;
use log::LevelFilter;
use std::borrow::Cow;
use termcolor2::Color;
#[derive(Debug, Clone, Copy)]
pub enum LevelPadding {
Left,
Right,
Off,
}
#[derive(Debug, Clone, Copy)]
pub enum ThreadPadding {
Left(usize),
Right(usize),
Off,
}
#[derive(Debug, Clone, Copy)]
pub enum TargetPadding {
Left(usize),
Right(usize),
Off,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ThreadLogMode {
IDs,
Names,
Both,
}
#[derive(Debug, Clone)]
pub(crate) enum TimeFormat {
Rfc2822,
Rfc3339,
Custom(&'static str),
}
#[allow(non_upper_case_globals, non_snake_case)]
pub mod Format {
pub const Time: u8 = 1;
pub const LevelFlag: u8 = 2;
pub const Thread: u8 = 4;
pub const FileLocation: u8 = 8;
pub const Target: u8 = 16;
pub const Module: u8 = 32;
}
pub enum LineEnding {
LF,
CR,
Crlf,
VT,
FF,
Nel,
LS,
PS,
}
#[derive(Debug, Clone)]
pub struct Config {
pub(crate) format: u8,
pub(crate) level_padding: LevelPadding,
pub(crate) thread_log_mode: ThreadLogMode,
pub(crate) thread_padding: ThreadPadding,
pub(crate) target_padding: TargetPadding,
pub(crate) min_level: LevelFilter,
pub(crate) max_level: LevelFilter,
pub(crate) time_format: TimeFormat,
pub(crate) filter_allow: Cow<'static, [Cow<'static, str>]>,
pub(crate) filter_ignore: Cow<'static, [Cow<'static, str>]>,
pub(crate) level_color: [Option<Color>; 6],
pub(crate) enable_colors: bool,
pub(crate) line_ending: String,
pub(crate) formatter: Option<String>,
}
impl Config {
pub fn builder() -> ConfigBuilder {
ConfigBuilder::new()
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct ConfigBuilder(Config);
impl ConfigBuilder {
pub fn new() -> ConfigBuilder {
ConfigBuilder(Config::default())
}
pub fn set_line_ending(&mut self, line_ending: LineEnding) -> &mut ConfigBuilder {
match line_ending {
LineEnding::LF => self.0.line_ending = String::from("\u{000A}"),
LineEnding::CR => self.0.line_ending = String::from("\u{000D}"),
LineEnding::Crlf => self.0.line_ending = String::from("\u{000D}\u{000A}"),
LineEnding::VT => self.0.line_ending = String::from("\u{000B}"),
LineEnding::FF => self.0.line_ending = String::from("\u{000C}"),
LineEnding::Nel => self.0.line_ending = String::from("\u{0085}"),
LineEnding::LS => self.0.line_ending = String::from("\u{2028}"),
LineEnding::PS => self.0.line_ending = String::from("\u{2029}"),
}
self
}
pub fn set_format(&mut self, format: u8) -> &mut ConfigBuilder {
self.0.format = format;
self
}
pub fn set_formatter(&mut self, formatter: Option<&str>) -> &mut ConfigBuilder {
self.0.formatter = formatter.map(|s| s.to_string());
self
}
pub fn set_min_level(&mut self, level: LevelFilter) -> &mut ConfigBuilder {
self.0.min_level = level;
self
}
pub fn set_max_level(&mut self, level: LevelFilter) -> &mut ConfigBuilder {
self.0.max_level = level;
self
}
pub fn set_enable_colors(&mut self, enable: bool) -> &mut ConfigBuilder {
self.0.enable_colors = enable;
self
}
pub fn set_target_padding(&mut self, padding: TargetPadding) -> &mut ConfigBuilder {
self.0.target_padding = padding;
self
}
pub fn set_level_padding(&mut self, padding: LevelPadding) -> &mut ConfigBuilder {
self.0.level_padding = padding;
self
}
pub fn set_thread_padding(&mut self, padding: ThreadPadding) -> &mut ConfigBuilder {
self.0.thread_padding = padding;
self
}
pub fn set_thread_mode(&mut self, mode: ThreadLogMode) -> &mut ConfigBuilder {
self.0.thread_log_mode = mode;
self
}
pub fn set_level_color(&mut self, level: Level, color: Option<Color>) -> &mut ConfigBuilder {
self.0.level_color[level as usize] = color;
self
}
pub fn set_time_format_custom(&mut self, time_format: &str) -> &mut ConfigBuilder {
self.0.time_format =
TimeFormat::Custom(Box::leak(time_format.to_string().into_boxed_str()));
self
}
pub fn set_time_format_rfc2822(&mut self) -> &mut ConfigBuilder {
self.0.time_format = TimeFormat::Rfc2822;
self
}
pub fn set_time_format_rfc3339(&mut self) -> &mut ConfigBuilder {
self.0.time_format = TimeFormat::Rfc3339;
self
}
pub fn add_filter_allow_str(&mut self, filter_allow: &'static str) -> &mut ConfigBuilder {
let mut list = Vec::from(&*self.0.filter_allow);
list.push(Cow::Borrowed(filter_allow));
self.0.filter_allow = Cow::Owned(list);
self
}
pub fn add_filter_allow(&mut self, filter_allow: String) -> &mut ConfigBuilder {
let mut list = Vec::from(&*self.0.filter_allow);
list.push(Cow::Owned(filter_allow));
self.0.filter_allow = Cow::Owned(list);
self
}
pub fn clear_filter_allow(&mut self) -> &mut ConfigBuilder {
self.0.filter_allow = Cow::Borrowed(&[]);
self
}
pub fn add_filter_ignore_str(&mut self, filter_ignore: &'static str) -> &mut ConfigBuilder {
let mut list = Vec::from(&*self.0.filter_ignore);
list.push(Cow::Borrowed(filter_ignore));
self.0.filter_ignore = Cow::Owned(list);
self
}
pub fn add_filter_ignore(&mut self, filter_ignore: String) -> &mut ConfigBuilder {
let mut list = Vec::from(&*self.0.filter_ignore);
list.push(Cow::Owned(filter_ignore));
self.0.filter_ignore = Cow::Owned(list);
self
}
pub fn clear_filter_ignore(&mut self) -> &mut ConfigBuilder {
self.0.filter_ignore = Cow::Borrowed(&[]);
self
}
pub fn build(&mut self) -> Config {
self.0.clone()
}
}
impl Default for ConfigBuilder {
fn default() -> Self {
ConfigBuilder::new()
}
}
impl Default for Config {
fn default() -> Config {
Config {
format: Format::LevelFlag | Format::Time | Format::Thread | Format::Target,
level_padding: LevelPadding::Off,
thread_log_mode: ThreadLogMode::IDs,
thread_padding: ThreadPadding::Off,
target_padding: TargetPadding::Off,
time_format: TimeFormat::Custom("%H:%M:%S"),
filter_allow: Cow::Borrowed(&[]),
filter_ignore: Cow::Borrowed(&[]),
enable_colors: true,
max_level: LevelFilter::Error,
min_level: LevelFilter::Trace,
formatter: None,
level_color: [
None, Some(Color::Red), Some(Color::Yellow), Some(Color::Blue), Some(Color::Cyan), Some(Color::White), ],
line_ending: String::from("\u{000A}"),
}
}
}