///|
// List slices are stored as raw values or raw strings.
pub(all) enum ListSlice {
RawData(Array[@types.LoroValue])
RawStr(str~ : String, unicode_len~ : Int)
} derive(Show)
///|
fn count_unicode_len(s : String) -> Int {
let mut len = 0
for _ in s {
len = len + 1
}
len
}
///|
pub fn ListSlice::from_str(str : String) -> ListSlice {
ListSlice::RawStr(str~, unicode_len=count_unicode_len(str))
}
///|
pub struct SliceRange {
start : UInt
end : UInt
} derive(Show, Eq)
///|
const UNKNOWN_START : UInt = 0x7fffffff
///|
pub fn SliceRange::is_unknown(self : SliceRange) -> Bool {
self.start == UNKNOWN_START
}
///|
pub fn SliceRange::new_unknown(size : UInt) -> SliceRange {
SliceRange::{ start: UNKNOWN_START, end: UNKNOWN_START + size }
}
///|
pub fn SliceRange::new(start : UInt, end : UInt) -> SliceRange {
SliceRange::{ start, end }
}
///|
pub fn SliceRange::start(self : SliceRange) -> UInt {
self.start
}
///|
pub fn SliceRange::end(self : SliceRange) -> UInt {
self.end
}
///|
pub fn SliceRange::len(self : SliceRange) -> Int {
(self.end - self.start).reinterpret_as_int()
}
///|
pub fn SliceRange::slice(self : SliceRange, from : Int, to : Int) -> SliceRange {
if self.is_unknown() {
SliceRange::new_unknown((to - from).reinterpret_as_uint())
} else {
SliceRange::{
start: self.start + from.reinterpret_as_uint(),
end: self.start + to.reinterpret_as_uint(),
}
}
}
///|
pub fn SliceRange::is_mergeable(self : SliceRange, other : SliceRange) -> Bool {
if self.is_unknown() && other.is_unknown() {
true
} else {
self.end == other.start
}
}
///|
pub fn SliceRange::merge(self : SliceRange, other : SliceRange) -> SliceRange {
if self.is_unknown() {
SliceRange::{ start: self.start, end: self.end + (other.end - other.start) }
} else {
SliceRange::{ start: self.start, end: other.end }
}
}
///|
fn slice_array(
values : Array[@types.LoroValue],
from : Int,
to : Int,
) -> Array[@types.LoroValue] {
let out : Array[@types.LoroValue] = []
for i = from; i < to; i = i + 1 {
out.push(values[i])
}
out
}
///|
fn slice_string_by_char(str : String, from : Int, to : Int) -> String {
let sb = StringBuilder::new()
let mut idx = 0
for ch in str {
if idx >= from && idx < to {
sb.write_char(ch)
}
if idx >= to {
break
}
idx = idx + 1
}
sb.to_string()
}
///|
pub fn ListSlice::content_len(self : ListSlice) -> Int {
match self {
RawData(values) => values.length()
RawStr(str=_, unicode_len~) => unicode_len
}
}
///|
pub fn ListSlice::slice(self : ListSlice, from : Int, to : Int) -> ListSlice {
match self {
RawData(values) => ListSlice::RawData(slice_array(values, from, to))
RawStr(str~, unicode_len=_) => {
let sliced = slice_string_by_char(str, from, to)
ListSlice::RawStr(str=sliced, unicode_len=to - from)
}
}
}
///|
pub fn ListSlice::is_mergeable(_self : ListSlice, _other : ListSlice) -> Bool {
false
}