use crate::event_store::event::MemoryEvent;
use crate::event_store::EventStore;
use std::sync::Arc;
pub struct TimelineReplay {
position: usize,
events: Vec<MemoryEvent>,
}
impl TimelineReplay {
pub fn new(event_store: Arc<EventStore>) -> Self {
let events = event_store.snapshot();
let mut sorted_events = events;
sorted_events.sort_by(|a, b| a.timestamp.cmp(&b.timestamp));
Self {
position: 0,
events: sorted_events,
}
}
pub fn reset(&mut self) {
self.position = 0;
}
pub fn advance_until(&mut self, timestamp: u64) -> Vec<MemoryEvent> {
let mut result = Vec::new();
for event in self.by_ref() {
if event.timestamp > timestamp {
break;
}
result.push(event);
}
result
}
pub fn get_events_between(&self, start: u64, end: u64) -> Vec<MemoryEvent> {
self.events
.iter()
.filter(|e| e.timestamp >= start && e.timestamp < end)
.cloned()
.collect()
}
pub fn len(&self) -> usize {
self.events.len()
}
pub fn is_empty(&self) -> bool {
self.events.is_empty()
}
pub fn position(&self) -> usize {
self.position
}
pub fn progress(&self) -> f64 {
if self.events.is_empty() {
0.0
} else {
self.position as f64 / self.events.len() as f64
}
}
}
impl Iterator for TimelineReplay {
type Item = MemoryEvent;
fn next(&mut self) -> Option<Self::Item> {
if self.position < self.events.len() {
let event = self.events[self.position].clone();
self.position += 1;
Some(event)
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_timeline_replay_creation() {
let event_store = Arc::new(EventStore::new());
let replay = TimelineReplay::new(event_store);
assert_eq!(replay.position(), 0);
assert!(replay.is_empty());
}
#[test]
fn test_timeline_replay_next() {
let event_store = Arc::new(EventStore::new());
let event = MemoryEvent::allocate(0x1000, 1024, 123);
event_store.record(event);
event_store.record(MemoryEvent::deallocate(0x1000, 1024, 456));
let mut replay = TimelineReplay::new(event_store);
assert_eq!(replay.len(), 2);
let first = replay.next();
assert!(first.is_some());
assert_eq!(first.unwrap().thread_id, 123);
let second = replay.next();
assert!(second.is_some());
assert_eq!(second.unwrap().thread_id, 456);
let third = replay.next();
assert!(third.is_none());
}
}