use crate::{now, FormatMode};
use alloc::vec::Vec;
use alloc::{format, string::String};
use core::cell::RefCell;
use core::fmt::{Debug, Display};
use log::LevelFilter;
pub type Entries<E> = Vec<Entry<E>>;
pub trait EntriesExt {
fn clear_timestamps(self) -> Self;
}
impl<E> EntriesExt for Entries<E> {
fn clear_timestamps(mut self) -> Entries<E> {
for entry in &mut self {
entry.timestamp = 0;
}
self
}
}
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Clone)]
pub struct Entry<E> {
pub content: EntryContent<E>,
pub timestamp: i64,
pub(crate) instant_display_displayed: RefCell<bool>,
}
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Clone)]
pub enum EntryContent<E> {
Error(E),
Message {
level: LevelFilter,
message: String,
},
}
impl<E> Entry<E> {
pub fn get_level(&self) -> LevelFilter {
match self.content {
EntryContent::Error(_) => LevelFilter::Error,
EntryContent::Message { level, .. } => level,
}
}
fn new(content: EntryContent<E>) -> Self {
Self {
content,
timestamp: now(),
instant_display_displayed: RefCell::new(false),
}
}
pub fn new_error(err: E) -> Self {
Self::new(EntryContent::Error(err))
}
pub fn new_message(level: LevelFilter, message: String) -> Self {
Self::new(EntryContent::Message { level, message })
}
}
impl<E: Debug + Display> Entry<E> {
pub fn get_message(&self, mode: &FormatMode) -> String {
match self.get_message_filter(mode, &LevelFilter::Trace) {
Some(msg) => msg,
None => unreachable!("No Message should get filtered."),
}
}
pub fn get_message_filter(&self, mode: &FormatMode, max_level: &LevelFilter) -> Option<String> {
match &self.content {
EntryContent::Error(err) => Some(match mode {
FormatMode::Normal => format!("{err}"),
FormatMode::Debug => format!("{err:?}"),
FormatMode::PrettyDebug => format!("{err:#?}"),
}),
EntryContent::Message {
message: msg,
level,
} => match level <= max_level {
true => Some(msg.clone()),
false => None,
},
}
}
}
impl<E> From<E> for Entry<E> {
fn from(value: E) -> Self {
Self::new_error(value)
}
}