use std::cmp::Ordering;
use content_tree::ContentLength;
use rle::{HasLength, MergableSpan, Searchable, SplitableSpan, SplitableSpanHelpers};
use crate::{AgentId, ROOT_AGENT};
use crate::dtrange::DTRange;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct CRDTId {
pub agent: AgentId,
pub seq: usize,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct CRDTSpan {
pub agent: AgentId,
pub seq_range: DTRange,
}
pub const CRDT_DOC_ROOT: CRDTId = CRDTId {
agent: ROOT_AGENT,
seq: 0
};
impl PartialOrd for CRDTId {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.agent != other.agent {
None
} else {
Some(self.seq.cmp(&other.seq))
}
}
}
impl Searchable for CRDTSpan {
type Item = CRDTId;
fn get_offset(&self, loc: CRDTId) -> Option<usize> {
if self.agent == loc.agent {
self.seq_range.get_offset(loc.seq)
} else { None }
}
fn at_offset(&self, offset: usize) -> CRDTId {
assert!(offset < self.len());
CRDTId {
agent: self.agent,
seq: self.seq_range.start + offset
}
}
}
impl ContentLength for CRDTSpan {
fn content_len(&self) -> usize {
self.seq_range.len()
}
fn content_len_at_offset(&self, offset: usize) -> usize {
offset
}
}
impl HasLength for CRDTSpan {
fn len(&self) -> usize {
self.seq_range.len()
}
}
impl SplitableSpanHelpers for CRDTSpan {
fn truncate_h(&mut self, at: usize) -> Self {
CRDTSpan {
agent: self.agent,
seq_range: self.seq_range.truncate(at)
}
}
fn truncate_keeping_right_h(&mut self, at: usize) -> Self {
CRDTSpan {
agent: self.agent,
seq_range: self.seq_range.truncate_keeping_right(at)
}
}
}
impl MergableSpan for CRDTSpan {
fn can_append(&self, other: &Self) -> bool {
self.agent == other.agent
&& self.seq_range.end == other.seq_range.start
}
fn append(&mut self, other: Self) {
self.seq_range.end = other.seq_range.end;
}
fn prepend(&mut self, other: Self) {
self.seq_range.start = other.seq_range.start;
}
}