use std::collections::VecDeque; use crate::log::{LogEvent, LogLevel, LogSource}; pub struct LogService { events: VecDeque, capacity: usize, next_seq: u64, } impl LogService { pub fn new(capacity: usize) -> Self { Self { events: VecDeque::with_capacity(capacity), capacity, next_seq: 0, } } pub fn log(&mut self, ts_ms: u64, frame: u64, level: LogLevel, source: LogSource, tag: u16, msg: String) { if self.events.len() >= self.capacity { self.events.pop_front(); } self.events.push_back(LogEvent { seq: self.next_seq, ts_ms, frame, level, source, tag, msg, }); self.next_seq += 1; } pub fn get_recent(&self, n: usize) -> Vec { self.events.iter().rev().take(n).cloned().collect::>().into_iter().rev().collect() } pub fn get_after(&self, seq: u64) -> Vec { self.events.iter().filter(|e| e.seq > seq).cloned().collect() } pub fn last_seq(&self) -> Option { self.events.back().map(|e| e.seq) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_ring_buffer_capacity() { let mut service = LogService::new(3); service.log(100, 1, LogLevel::Info, LogSource::Pos, 0, "Log 1".to_string()); service.log(110, 1, LogLevel::Info, LogSource::Pos, 0, "Log 2".to_string()); service.log(120, 1, LogLevel::Info, LogSource::Pos, 0, "Log 3".to_string()); assert_eq!(service.events.len(), 3); assert_eq!(service.events[0].msg, "Log 1"); service.log(130, 1, LogLevel::Info, LogSource::Pos, 0, "Log 4".to_string()); assert_eq!(service.events.len(), 3); assert_eq!(service.events[0].msg, "Log 2"); assert_eq!(service.events[2].msg, "Log 4"); } #[test] fn test_get_recent() { let mut service = LogService::new(10); for i in 0..5 { service.log(i as u64, 1, LogLevel::Info, LogSource::Pos, 0, format!("Log {}", i)); } let recent = service.get_recent(2); assert_eq!(recent.len(), 2); assert_eq!(recent[0].msg, "Log 3"); assert_eq!(recent[1].msg, "Log 4"); } #[test] fn test_get_after() { let mut service = LogService::new(10); for i in 0..5 { service.log(i as u64, 1, LogLevel::Info, LogSource::Pos, 0, format!("Log {}", i)); } let after = service.get_after(2); // seqs are 0, 1, 2, 3, 4. Should return 3 and 4. assert_eq!(after.len(), 2); assert_eq!(after[0].msg, "Log 3"); assert_eq!(after[1].msg, "Log 4"); } }