loro-delta 1.9.1

Loro internal library. It's used as a delta between two versions of text or lists. It's also an efficient Rope.
Documentation
use generic_btree::rle::{HasLength, Mergeable, Sliceable, TryInsert};

use crate::delta_trait::DeltaValue;

#[derive(Debug, Clone)]
pub struct AsUtf16Index<S: AsRef<str>> {
    s: S,
    utf16_len: usize,
}

impl<S: AsRef<str>> AsUtf16Index<S> {
    pub fn new(s: S) -> Self {
        let utf16_len = s
            .as_ref()
            .chars()
            .fold(0, |prev, cur| prev + cur.len_utf16());
        Self { s, utf16_len }
    }

    fn convert_utf16_to_utf8(&self, index: usize) -> usize {
        if index == 0 {
            return 0;
        }

        let s = self.s.as_ref();
        if index == self.utf16_len {
            return s.len();
        }

        if index > self.utf16_len {
            panic!("Index out of bounds");
        }

        let mut utf16_index = 0;
        for (i, c) in s.char_indices() {
            if utf16_index >= index {
                return i;
            }
            utf16_index += c.len_utf16();
        }

        unreachable!();
    }

    #[allow(unused)]
    fn convert_utf8_to_utf16(&self, index: usize) -> usize {
        if index == 0 {
            return 0;
        }

        let s = self.s.as_ref();
        if index == s.len() {
            return self.utf16_len;
        }

        if index > s.len() {
            panic!("Index out of bounds");
        }

        let mut utf16_index = 0;
        for (i, c) in s.char_indices() {
            if i >= index {
                return utf16_index;
            }
            utf16_index += c.len_utf16();
        }

        unreachable!();
    }
}

impl<S: AsRef<str>> HasLength for AsUtf16Index<S> {
    fn rle_len(&self) -> usize {
        self.utf16_len
    }
}

impl<S: AsRef<str> + Mergeable> Mergeable for AsUtf16Index<S> {
    fn can_merge(&self, rhs: &Self) -> bool {
        self.s.can_merge(&rhs.s)
    }

    fn merge_right(&mut self, rhs: &Self) {
        self.s.merge_right(&rhs.s);
        self.utf16_len += rhs.utf16_len;
    }

    fn merge_left(&mut self, left: &Self) {
        self.s.merge_left(&left.s);
        self.utf16_len += left.utf16_len;
    }
}

impl<S: AsRef<str> + Sliceable> Sliceable for AsUtf16Index<S> {
    fn _slice(&self, range: std::ops::Range<usize>) -> Self {
        let start = self.convert_utf16_to_utf8(range.start);
        let end = self.convert_utf16_to_utf8(range.end);
        Self {
            s: self.s._slice(start..end),
            utf16_len: range.len(),
        }
    }
}

impl<S: AsRef<str> + Sliceable + TryInsert> TryInsert for AsUtf16Index<S> {
    fn try_insert(&mut self, pos: usize, elem: Self) -> Result<(), Self>
    where
        Self: Sized,
    {
        let start = self.convert_utf16_to_utf8(pos);
        match self.s.try_insert(start, elem.s) {
            Ok(()) => {
                self.utf16_len += elem.utf16_len;
                Ok(())
            }
            Err(e) => Err(Self {
                s: e,
                utf16_len: elem.utf16_len,
            }),
        }
    }
}

impl<S: AsRef<str> + DeltaValue> Default for AsUtf16Index<S> {
    fn default() -> Self {
        Self {
            s: S::default(),
            utf16_len: 0,
        }
    }
}

impl<S: AsRef<str> + DeltaValue> DeltaValue for AsUtf16Index<S> {}