use core::convert::Infallible;
use core::fmt;
use core::iter::FromIterator;
use core::ops::Bound::*;
use std::collections::BTreeSet;
use serde::{Deserialize, Serialize};
use crate::{CmRDT, CvRDT, Identifier};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Op<T> {
Insert {
id: Identifier<T>,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct GList<T: Ord> {
list: BTreeSet<Identifier<T>>,
}
impl<T: fmt::Display + Ord> fmt::Display for GList<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "GList[")?;
let mut iter = self.list.iter();
if let Some(e) = iter.next() {
write!(f, "{}", e)?;
}
for e in iter {
write!(f, "{}", e)?;
}
write!(f, "]")
}
}
impl<T: Ord> Default for GList<T> {
fn default() -> Self {
Self {
list: Default::default(),
}
}
}
impl<T: Ord + Clone> GList<T> {
pub fn new() -> Self {
Self::default()
}
pub fn read<'a, C: FromIterator<&'a T>>(&'a self) -> C {
self.list.iter().map(|id| id.value()).collect()
}
pub fn read_into<C: FromIterator<T>>(self) -> C {
self.list.into_iter().map(|id| id.into_value()).collect()
}
pub fn iter(&self) -> std::collections::btree_set::Iter<Identifier<T>> {
self.list.iter()
}
pub fn get(&self, idx: usize) -> Option<&Identifier<T>> {
self.list.iter().nth(idx)
}
pub fn insert_before(&self, high_id_opt: Option<&Identifier<T>>, elem: T) -> Op<T> {
let low_id_opt = high_id_opt.and_then(|high_id| {
self.list
.range((Unbounded, Excluded(high_id.clone())))
.rev()
.find(|id| id < &high_id)
});
let id = Identifier::between(low_id_opt, high_id_opt, elem);
Op::Insert { id }
}
pub fn insert_after(&self, low_id_opt: Option<&Identifier<T>>, elem: T) -> Op<T> {
let high_id_opt = low_id_opt.and_then(|low_id| {
self.list
.range((Excluded(low_id.clone()), Unbounded))
.find(|id| id > &low_id)
});
let id = Identifier::between(low_id_opt, high_id_opt, elem);
Op::Insert { id }
}
pub fn len(&self) -> usize {
self.list.len()
}
pub fn is_empty(&self) -> bool {
self.list.is_empty()
}
pub fn first(&self) -> Option<&Identifier<T>> {
self.iter().next()
}
pub fn last(&self) -> Option<&Identifier<T>> {
self.iter().next_back()
}
}
impl<T: Ord> CmRDT for GList<T> {
type Op = Op<T>;
type Validation = Infallible;
fn validate_op(&self, _: &Self::Op) -> Result<(), Self::Validation> {
Ok(())
}
fn apply(&mut self, op: Self::Op) {
match op {
Op::Insert { id } => self.list.insert(id),
};
}
}
impl<T: Ord> CvRDT for GList<T> {
type Validation = Infallible;
fn validate_merge(&self, _: &Self) -> Result<(), Self::Validation> {
Ok(())
}
fn merge(&mut self, other: Self) {
self.list.extend(other.list)
}
}
#[cfg(feature = "quickcheck")]
use quickcheck::{Arbitrary, Gen};
#[cfg(feature = "quickcheck")]
impl<T: Arbitrary> Arbitrary for Op<T> {
fn arbitrary(g: &mut Gen) -> Self {
let id = Identifier::arbitrary(g);
Op::Insert { id }
}
}