crdt-richtext 0.1.1

Richtext CRDT, Rust implementation of Peritext and Fugue
Documentation
use super::*;
use generic_btree::{rle, BTreeTrait};

#[derive(Debug, Clone)]
pub(crate) struct RichTreeTrait;

impl BTreeTrait for RichTreeTrait {
    type Elem = Elem;

    type Cache = Cache;

    type CacheDiff = CacheDiff;

    const MAX_LEN: usize = 32;

    fn calc_cache_internal(
        cache: &mut Self::Cache,
        caches: &[generic_btree::Child<Self>],
        diff: Option<Self::CacheDiff>,
    ) -> Option<Self::CacheDiff> {
        match diff {
            Some(diff) => {
                cache.apply_diff(&diff);
                Some(diff)
            }
            None => {
                let mut len = 0;
                let mut utf16_len = 0;
                let mut anchor_set = CacheAnchorSet::default();
                for child in caches.iter() {
                    len += child.cache.len;
                    utf16_len += child.cache.utf16_len;
                    anchor_set.union_(&child.cache.anchor_set);
                }

                let anchor_diff = anchor_set.calc_diff(&cache.anchor_set);
                let diff = CacheDiff {
                    anchor_diff,
                    len_diff: len as isize - cache.len as isize,
                    utf16_len_diff: utf16_len as isize - cache.utf16_len as isize,
                };

                cache.len = len;
                cache.utf16_len = utf16_len;
                Some(diff)
            }
        }
    }

    fn calc_cache_leaf(
        cache: &mut Self::Cache,
        caches: &[Self::Elem],
        diff: Option<Self::CacheDiff>,
    ) -> Self::CacheDiff {
        match diff {
            Some(diff) => {
                cache.apply_diff(&diff);
                diff
            }
            None => {
                let mut len = 0;
                let mut utf16_len = 0;
                let mut anchor_set = CacheAnchorSet::default();
                for child in caches.iter() {
                    if !child.is_dead() {
                        len += child.string.len();
                        utf16_len += child.utf16_len;
                    }
                    anchor_set.union_elem_set(&child.anchor_set);
                }

                let anchor_diff = cache.anchor_set.calc_diff(&anchor_set);
                let diff = CacheDiff {
                    anchor_diff,
                    len_diff: len as isize - cache.len as isize,
                    utf16_len_diff: utf16_len as isize - cache.utf16_len as isize,
                };
                cache.len = len as u32;
                cache.utf16_len = utf16_len;
                diff
            }
        }
    }

    fn merge_cache_diff(diff1: &mut Self::CacheDiff, diff2: &Self::CacheDiff) {
        diff1.anchor_diff.merge(&diff2.anchor_diff);
        diff1.len_diff += diff2.len_diff;
        diff1.utf16_len_diff += diff2.utf16_len_diff;
    }

    fn insert(
        elements: &mut generic_btree::HeapVec<Self::Elem>,
        index: usize,
        offset: usize,
        elem: Self::Elem,
    ) {
        rle::insert_with_split(elements, index, offset, elem)
    }
}