use super::causal::VClock;
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeltaBuffer<D> {
deltas: VecDeque<(VClock, D)>,
max_size: usize,
oldest_version: VClock,
}
impl<D: Clone> DeltaBuffer<D> {
pub fn new(max_size: usize) -> Self {
Self {
deltas: VecDeque::with_capacity(max_size),
max_size,
oldest_version: VClock::new(),
}
}
pub fn push(&mut self, version: VClock, delta: D) {
if self.deltas.len() >= self.max_size {
if let Some((old_version, _)) = self.deltas.pop_front() {
self.oldest_version = old_version;
}
}
self.deltas.push_back((version, delta));
}
pub fn deltas_since(&self, version: &VClock) -> Option<Vec<D>> {
if self.oldest_version != VClock::new() && self.oldest_version.dominates(version) {
return None;
}
let result: Vec<D> = self
.deltas
.iter()
.filter(|(v, _)| !version.dominates(v))
.map(|(_, d)| d.clone())
.collect();
Some(result)
}
pub fn can_serve(&self, version: &VClock) -> bool {
self.deltas_since(version).is_some()
}
pub fn len(&self) -> usize {
self.deltas.len()
}
pub fn is_empty(&self) -> bool {
self.deltas.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_buffer_new() {
let buf: DeltaBuffer<i32> = DeltaBuffer::new(10);
assert!(buf.is_empty());
}
#[test]
fn test_buffer_push_and_retrieve() {
let mut buf: DeltaBuffer<i32> = DeltaBuffer::new(10);
let mut clock = VClock::new();
clock.increment(1);
buf.push(clock, 42);
let empty = VClock::new();
let deltas = buf.deltas_since(&empty).unwrap();
assert_eq!(deltas, vec![42]);
}
#[test]
fn test_buffer_multiple_deltas() {
let mut buf: DeltaBuffer<i32> = DeltaBuffer::new(10);
let mut clock = VClock::new();
clock.increment(1);
buf.push(clock.clone(), 1);
clock.increment(1);
buf.push(clock.clone(), 2);
clock.increment(1);
buf.push(clock.clone(), 3);
let empty = VClock::new();
let deltas = buf.deltas_since(&empty).unwrap();
assert_eq!(deltas, vec![1, 2, 3]);
}
#[test]
fn test_buffer_since_version() {
let mut buf: DeltaBuffer<i32> = DeltaBuffer::new(10);
let mut clock = VClock::new();
clock.increment(1);
let v1 = clock.clone();
buf.push(clock.clone(), 1);
clock.increment(1);
buf.push(clock.clone(), 2);
clock.increment(1);
buf.push(clock.clone(), 3);
let deltas = buf.deltas_since(&v1).unwrap();
assert_eq!(deltas, vec![2, 3]);
}
#[test]
fn test_buffer_overflow() {
let mut buf: DeltaBuffer<i32> = DeltaBuffer::new(2);
let mut clock = VClock::new();
clock.increment(1);
buf.push(clock.clone(), 1);
clock.increment(1);
buf.push(clock.clone(), 2);
clock.increment(1);
buf.push(clock.clone(), 3);
let empty = VClock::new();
assert!(buf.deltas_since(&empty).is_none());
}
#[test]
fn test_buffer_overflow_partial() {
let mut buf: DeltaBuffer<i32> = DeltaBuffer::new(2);
let mut clock = VClock::new();
clock.increment(1);
let v1 = clock.clone();
buf.push(clock.clone(), 1);
clock.increment(1);
let v2 = clock.clone();
buf.push(clock.clone(), 2);
clock.increment(1);
buf.push(clock.clone(), 3);
assert!(buf.deltas_since(&v1).is_none());
let deltas = buf.deltas_since(&v2).unwrap();
assert_eq!(deltas, vec![3]);
}
}