use std::cell::RefCell;
use std::collections::VecDeque;
use std::thread::LocalKey;
use crate::NanoTimeStamp;
use super::LogEntry;
pub struct LogBuffer {
max_capacity: usize,
entries: VecDeque<LogEntry>,
}
impl LogBuffer {
pub fn with_capacity(max_capacity: usize) -> Self {
Self {
max_capacity,
entries: VecDeque::with_capacity(max_capacity),
}
}
pub fn set_capacity(&mut self, new_capacity: usize) {
while self.entries.len() > new_capacity {
self.entries.pop_back();
}
self.max_capacity = new_capacity;
}
pub fn append(&mut self, entry: LogEntry) {
if self.entries.len() >= self.max_capacity {
self.entries.pop_back();
}
self.entries.push_front(entry);
}
pub fn iter(&self) -> impl Iterator<Item = &LogEntry> {
self.entries.iter()
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn max_capacity(&self) -> usize {
self.max_capacity
}
pub fn entries_partition_point<P>(&self, p: P) -> impl Iterator<Item = &LogEntry>
where
P: Fn(&LogEntry) -> bool,
{
let head_len = self.entries.partition_point(p);
self.iter().skip(head_len)
}
pub fn export(&self) -> Vec<LogEntry> {
self.iter().cloned().collect()
}
pub fn export_since(&self, timestamp: NanoTimeStamp) -> Vec<LogEntry> {
self.entries_partition_point(|entry| entry.timestamp > timestamp)
.cloned()
.collect()
}
pub fn export_page(&self, page: usize, page_size: usize) -> Vec<LogEntry> {
let start = page * page_size;
let end = start + page_size;
self.iter().skip(start).take(end - start).cloned().collect()
}
pub fn export_messages(&self) -> Vec<String> {
self.iter().map(|entry| entry.to_string()).collect()
}
pub fn export_messages_since(&self, timestamp: NanoTimeStamp) -> Vec<String> {
self.entries_partition_point(|entry| entry.timestamp > timestamp)
.map(|entry| entry.to_string())
.collect()
}
pub fn export_messages_page(&self, page: usize, page_size: usize) -> Vec<String> {
let start = page * page_size;
let end = start + page_size;
self.iter()
.skip(start)
.take(end - start)
.map(|entry| entry.to_string())
.collect()
}
}
pub type GlobalBuffer = LocalKey<RefCell<LogBuffer>>;
#[derive(Clone)]
pub struct DevNull;
pub trait Sink {
fn append(&self, entry: LogEntry);
}
impl Sink for DevNull {
fn append(&self, _: LogEntry) {}
}
impl Sink for &'static GlobalBuffer {
fn append(&self, entry: LogEntry) {
self.with(|cell| cell.borrow_mut().append(entry))
}
}