feat: readonly arena

This commit is contained in:
Zixuan Chen 2023-07-07 15:36:19 +08:00
parent fd588beee2
commit cc4e1d02e4

View file

@ -7,8 +7,8 @@ use crate::{
};
/// This is shared between [OpLog] and [AppState].
/// It uses a immutable data structure inside so that we have O(1) clone time.
/// It can make sharing data between threads easier.
/// It only takes O(1) to have a readonly view cloned.
/// It makes ownership problem easier.
///
#[derive(Clone, Default)]
pub(super) struct SharedArena {
@ -20,6 +20,15 @@ pub(super) struct SharedArena {
values: Vector<LoroValue>,
}
pub(super) struct ReadonlyArena {
container_idx_to_id: Vector<ContainerID>,
container_id_to_idx: im::HashMap<ContainerID, ContainerIdx>,
/// The parent of each container.
parents: im::HashMap<ContainerIdx, Option<ContainerIdx>>,
bytes: BytesSlice,
values: Vector<LoroValue>,
}
impl SharedArena {
pub fn register_container(&mut self, id: &ContainerID) -> ContainerIdx {
if let Some(&idx) = self.container_id_to_idx.get(id) {
@ -60,4 +69,56 @@ impl SharedArena {
(start, self.values.len())
}
pub fn to_readonly(&self) -> ReadonlyArena {
ReadonlyArena {
container_idx_to_id: self.container_idx_to_id.clone(),
container_id_to_idx: self.container_id_to_idx.clone(),
parents: self.parents.clone(),
bytes: self.bytes.slice(..),
values: self.values.clone(),
}
}
pub fn set_parent(&mut self, child: ContainerIdx, parent: Option<ContainerIdx>) {
self.parents.insert(child, parent);
}
pub fn get_parent(&self, child: ContainerIdx) -> Option<ContainerIdx> {
self.parents.get(&child).copied().flatten()
}
pub fn slice_bytes(&self, range: std::ops::Range<usize>) -> &[u8] {
&self.bytes[range]
}
pub fn get_value(&self, idx: usize) -> Option<&LoroValue> {
self.values.get(idx)
}
pub fn get_value_mut(&mut self, idx: usize) -> Option<&mut LoroValue> {
self.values.get_mut(idx)
}
}
impl ReadonlyArena {
pub fn id_to_idx(&self, id: &ContainerID) -> Option<ContainerIdx> {
self.container_id_to_idx.get(id).copied()
}
pub fn idx_to_id(&self, id: ContainerIdx) -> Option<&ContainerID> {
self.container_idx_to_id.get(id.to_u32() as usize)
}
pub fn slice_bytes(&self, range: std::ops::Range<usize>) -> &[u8] {
&self.bytes[range]
}
pub fn get_value(&self, idx: usize) -> Option<&LoroValue> {
self.values.get(idx)
}
pub fn get_parent(&self, child: ContainerIdx) -> Option<ContainerIdx> {
self.parents.get(&child).copied().flatten()
}
}