Piotr OsiewiczRust 1.85 (#25272)e4e758d1 year agoHistory
161 lines · 3.6 KB · Rust
RawDownload
use std::{fmt::Debug, ops::Add};use sum_tree::{Dimension, Edit, Item, KeyedItem, SumTree, Summary}; pub trait Operation: Clone + Debug {    fn lamport_timestamp(&self) -> clock::Lamport;} #[derive(Clone, Debug)]struct OperationItem<T>(T); #[derive(Clone, Debug)]pub struct OperationQueue<T: Operation>(SumTree<OperationItem<T>>); #[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]pub struct OperationKey(clock::Lamport); #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]pub struct OperationSummary {    pub key: OperationKey,    pub len: usize,} impl OperationKey {    pub fn new(timestamp: clock::Lamport) -> Self {        Self(timestamp)    }} impl<T: Operation> Default for OperationQueue<T> {    fn default() -> Self {        OperationQueue::new()    }} impl<T: Operation> OperationQueue<T> {    pub fn new() -> Self {        OperationQueue(SumTree::default())    }     pub fn len(&self) -> usize {        self.0.summary().len    }     pub fn is_empty(&self) -> bool {        self.len() == 0    }     pub fn insert(&mut self, mut ops: Vec<T>) {        ops.sort_by_key(|op| op.lamport_timestamp());        ops.dedup_by_key(|op| op.lamport_timestamp());        self.0.edit(            ops.into_iter()                .map(|op| Edit::Insert(OperationItem(op)))                .collect(),            &(),        );    }     pub fn drain(&mut self) -> Self {        let clone = self.clone();        self.0 = SumTree::default();        clone    }     pub fn iter(&self) -> impl Iterator<Item = &T> {        self.0.iter().map(|i| &i.0)    }} impl Summary for OperationSummary {    type Context = ();     fn zero(_cx: &()) -> Self {        Default::default()    }     fn add_summary(&mut self, other: &Self, _: &()) {        assert!(self.key < other.key);        self.key = other.key;        self.len += other.len;    }} impl Add<&Self> for OperationSummary {    type Output = Self;     fn add(self, other: &Self) -> Self {        assert!(self.key < other.key);        OperationSummary {            key: other.key,            len: self.len + other.len,        }    }} impl Dimension<'_, OperationSummary> for OperationKey {    fn zero(_cx: &()) -> Self {        Default::default()    }     fn add_summary(&mut self, summary: &OperationSummary, _: &()) {        assert!(*self <= summary.key);        *self = summary.key;    }} impl<T: Operation> Item for OperationItem<T> {    type Summary = OperationSummary;     fn summary(&self, _cx: &()) -> Self::Summary {        OperationSummary {            key: OperationKey::new(self.0.lamport_timestamp()),            len: 1,        }    }} impl<T: Operation> KeyedItem for OperationItem<T> {    type Key = OperationKey;     fn key(&self) -> Self::Key {        OperationKey::new(self.0.lamport_timestamp())    }} #[cfg(test)]mod tests {    use super::*;     #[test]    fn test_len() {        let mut clock = clock::Lamport::new(0);         let mut queue = OperationQueue::new();        assert_eq!(queue.len(), 0);         queue.insert(vec![            TestOperation(clock.tick()),            TestOperation(clock.tick()),        ]);        assert_eq!(queue.len(), 2);         queue.insert(vec![TestOperation(clock.tick())]);        assert_eq!(queue.len(), 3);         drop(queue.drain());        assert_eq!(queue.len(), 0);         queue.insert(vec![TestOperation(clock.tick())]);        assert_eq!(queue.len(), 1);    }     #[derive(Clone, Debug, Eq, PartialEq)]    struct TestOperation(clock::Lamport);     impl Operation for TestOperation {        fn lamport_timestamp(&self) -> clock::Lamport {            self.0        }    }}