#![allow(unused_variables)]
use crate::{
options::{self, Options},
submodule::Submodule,
facades::FacadeVariant,
level::Level,
ErrorKind::ScopeNotInitialized,
Scope, LogKey, Result,
util::read_var_from_env,
};
use std::{
vec::Vec,
ops::{Index, IndexMut},
fmt::{self, Display},
};
#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[allow(clippy::upper_case_acronyms)]
pub enum ScopeKey {
#[default]
Application = 0,
CLog,
Lib,
#[doc(hidden)]
MAX, }
impl Display for ScopeKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::Application => f.write_str("application"),
Self::CLog => f.write_str("hclog"),
Self::Lib => f.write_str("library"),
Self::MAX => f.write_str("max"),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub (crate) enum ScopeEnv {
#[default]
Global,
Task,
}
impl fmt::Display for ScopeEnv {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::Global => f.write_str("global"),
Self::Task => f.write_str("task"),
}
}
}
#[derive(Debug, Default)]
pub (crate) struct LogScope {
name: String,
lm: ScopeKey,
env: ScopeEnv,
env_ident: Option<String>,
initialized: bool,
submodules: Vec<Submodule>,
default_options: Options,
default_facade: FacadeVariant,
default_level: Level,
}
impl<K> Index<K> for LogScope where K: LogKey {
type Output = Submodule;
fn index(&self, index: K) -> &Self::Output {
&self.submodules[index.log_key()]
}
}
impl<K> IndexMut<K> for LogScope where K: LogKey {
fn index_mut(&mut self, index: K) -> &mut Self::Output {
&mut self.submodules[index.log_key()]
}
}
impl LogScope {
pub (crate) fn init<I: Scope, S: Display>(
name: S, level: Level, facade: FacadeVariant, options: Options
) -> Result<Self> {
let mut default_level = level;
if let Ok(Some(l)) = read_var_from_env::<Level>(options::ENV_OPT_LEVEL) {
default_level = l;
};
let mut default_facade = facade;
if let Ok(Some(f)) = read_var_from_env::<FacadeVariant>(options::ENV_OPT_FACADE) {
default_facade = f;
}
let mut default_options = options;
default_options.parse_from_env()?;
Ok(Self {
name: name.to_string(),
lm: I::logscope(),
env: ScopeEnv::Global,
initialized: true,
default_options,
default_facade,
default_level,
..Default::default()
})
}
pub (crate) fn to_scoped(&self, ident: impl fmt::Display) -> Self {
Self {
env: ScopeEnv::Task,
env_ident: Some(ident.to_string()),
name: self.name.clone(),
lm: self.lm,
initialized: self.initialized,
default_options: self.default_options,
default_facade: self.default_facade.clone(),
default_level: self.default_level,
submodules: self.submodules.clone(),
}
}
pub (crate) fn initialized(&self) -> bool {
self.initialized
}
pub (crate) fn name(&self) -> &str {
&self.name
}
pub (crate) fn key(&self) -> ScopeKey {
self.lm
}
pub (crate) fn env(&self) -> ScopeEnv {
self.env
}
pub (crate) fn env_ident(&self) -> Option<&str> {
self.env_ident.as_deref()
}
pub (crate) fn has_submodule<K: LogKey>(&self, key: K) -> bool {
let ckey = key.log_key();
if !self.initialized || self.submodules.len() <= ckey {
return false;
}
let submod = &self.submodules[ckey];
if !submod.initialized() || submod.key() != ckey {
return false;
}
true
}
pub (crate) fn add_submodule<K: LogKey>(&mut self, submod: K)
-> Result<&mut Submodule>
{
if !self.initialized {
return Err(ScopeNotInitialized);
}
let level = submod.init_level().unwrap_or(self.default_level);
let facade = submod.init_facade().unwrap_or(self.default_facade.clone());
let opts = submod.init_options().unwrap_or(self.default_options);
match self.submodules.get_mut(submod.log_key()) {
Some(sub) => {
if !sub.initialized() {
*sub = Submodule::new(submod, level, &facade, opts);
}
}
None => {
if self.submodules.len() != submod.log_key() {
for _ in self.submodules.len()..submod.log_key() {
self.submodules.push(Submodule::default());
}
}
self.submodules.push(Submodule::new(submod, level, &facade, opts));
}
}
Ok(&mut self.submodules[submod.log_key()])
}
pub (crate) fn submodules(&self) -> impl Iterator<Item = &Submodule> {
self.submodules.iter()
}
pub (crate) fn submodules_mut(&mut self) -> impl Iterator<Item = &mut Submodule> {
self.submodules.iter_mut()
}
pub (crate) fn get_submodule<K: LogKey>(&self, key: K) -> Option<&Submodule> {
self.submodules.get(key.log_key())
}
pub (crate) fn get_submodule_mut<K: LogKey>(&mut self, key: K) -> Option<&mut Submodule> {
self.submodules.get_mut(key.log_key())
}
pub (crate) fn get_submod_by_name(&mut self, key: &str) -> Option<&mut Submodule> {
if self.submodules.is_empty() {
return None;
}
self.submodules.iter_mut().find(|submod| submod.name() == key)
}
}