use std::collections::VecDeque;
use std::sync::Arc;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
}
impl LogLevel {
pub fn label(self) -> &'static str {
match self {
Self::Trace => "TRACE",
Self::Debug => "DEBUG",
Self::Info => "INFO",
Self::Warn => "WARN",
Self::Error => "ERROR",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LogEntry {
pub level: LogLevel,
pub message: Arc<str>,
}
impl LogEntry {
pub fn new(level: LogLevel, message: impl Into<Arc<str>>) -> Self {
Self {
level,
message: message.into(),
}
}
pub fn info(message: impl Into<Arc<str>>) -> Self {
Self::new(LogLevel::Info, message)
}
pub fn warn(message: impl Into<Arc<str>>) -> Self {
Self::new(LogLevel::Warn, message)
}
pub fn error(message: impl Into<Arc<str>>) -> Self {
Self::new(LogLevel::Error, message)
}
}
#[derive(Clone, Debug)]
pub struct LogBuffer {
entries: VecDeque<LogEntry>,
capacity: usize,
paused: bool,
pause_len: usize,
}
impl LogBuffer {
pub fn new(capacity: usize) -> Self {
Self {
entries: VecDeque::new(),
capacity: capacity.max(1),
paused: false,
pause_len: 0,
}
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn push(&mut self, entry: LogEntry) {
self.entries.push_back(entry);
while self.entries.len() > self.capacity {
self.entries.pop_front();
}
if self.paused {
self.pause_len = self.pause_len.min(self.entries.len());
}
}
pub fn extend<I>(&mut self, entries: I)
where
I: IntoIterator<Item = LogEntry>,
{
for entry in entries {
self.push(entry);
}
}
pub fn clear(&mut self) {
self.entries.clear();
self.pause_len = 0;
}
pub fn set_paused(&mut self, paused: bool) {
if paused && !self.paused {
self.pause_len = self.entries.len();
}
if !paused {
self.pause_len = 0;
}
self.paused = paused;
}
pub fn paused(&self) -> bool {
self.paused
}
pub fn snapshot(&self) -> Arc<[LogEntry]> {
let visible_len = if self.paused {
self.pause_len.min(self.entries.len())
} else {
self.entries.len()
};
self.entries
.iter()
.take(visible_len)
.cloned()
.collect::<Vec<_>>()
.into()
}
}