///|
// Shared arena for list values.
pub struct SharedArena {
values : Array[@types.LoroValue]
}
///|
pub fn SharedArena::new() -> SharedArena {
SharedArena::{ values: [] }
}
///|
pub fn SharedArena::alloc_values(
self : SharedArena,
values : Array[@types.LoroValue],
) -> @op.SliceRange {
let start = self.values.length().reinterpret_as_uint()
for v in values {
self.values.push(v)
}
let end = self.values.length().reinterpret_as_uint()
@op.SliceRange::new(start, end)
}
///|
pub fn SharedArena::get_values(
self : SharedArena,
range : @op.SliceRange,
) -> Array[@types.LoroValue] {
if range.is_unknown() {
[]
} else {
let out : Array[@types.LoroValue] = []
let start = range.start().reinterpret_as_int()
let end = range.end().reinterpret_as_int()
for i = start; i < end; i = i + 1 {
out.push(self.values[i])
}
out
}
}
///|
// Convert a RawOp into a persisted Op using arena storage for list inserts.
pub fn SharedArena::to_persisted_op(
self : SharedArena,
op : @op.RawOp,
) -> @op.Op {
let content = match op.content() {
@op.RawOpContent::Map(map_set) => @op.InnerContent::Map(map_set)
@op.RawOpContent::List(list_op) =>
@op.InnerContent::List(raw_list_to_inner(self, list_op))
@op.RawOpContent::Tree(tree_op) => @op.InnerContent::Tree(tree_op)
@op.RawOpContent::Counter(counter_op) =>
@op.InnerContent::Counter(counter_op)
}
let id = op.id()
@op.Op::new(id.counter, op.container(), content)
}
///|
fn raw_list_to_inner(
arena : SharedArena,
list_op : @op.ListOp,
) -> @op.InnerListOp {
match list_op {
@op.ListOp::Insert(slice~, pos~) =>
match slice {
@op.ListSlice::RawData(values) => {
let range = arena.alloc_values(values)
@op.InnerListOp::Insert(slice=range, pos~)
}
@op.ListSlice::RawStr(str~, unicode_len=len) =>
@op.InnerListOp::InsertText(
str~,
unicode_start=0,
unicode_len=len,
pos~,
)
}
@op.ListOp::Delete(span) => @op.InnerListOp::Delete(span)
@op.ListOp::Move(from~, to~, elem_id~) =>
@op.InnerListOp::Move(from~, elem_id~, to~)
@op.ListOp::Set(elem_id~, value~) => @op.InnerListOp::Set(elem_id~, value~)
@op.ListOp::StyleStart(start~, end~, key~, info~, value~) =>
@op.InnerListOp::StyleStart(start~, end~, key~, info~, value~)
@op.ListOp::StyleEnd => @op.InnerListOp::StyleEnd
}
}