mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-23 13:39:12 +00:00
Merge pull request #22 from loro-dev/refactor-map
Refactor: add pool to map
This commit is contained in:
commit
50ec756e6b
8 changed files with 100 additions and 53 deletions
28
crates/loro-core/deno.lock
Normal file
28
crates/loro-core/deno.lock
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"version": "2",
|
||||
"remote": {
|
||||
"https://deno.land/std@0.105.0/_util/assert.ts": "2f868145a042a11d5ad0a3c748dcf580add8a0dbc0e876eaa0026303a5488f58",
|
||||
"https://deno.land/std@0.105.0/_util/os.ts": "dfb186cc4e968c770ab6cc3288bd65f4871be03b93beecae57d657232ecffcac",
|
||||
"https://deno.land/std@0.105.0/path/_constants.ts": "1247fee4a79b70c89f23499691ef169b41b6ccf01887a0abd131009c5581b853",
|
||||
"https://deno.land/std@0.105.0/path/_interface.ts": "1fa73b02aaa24867e481a48492b44f2598cd9dfa513c7b34001437007d3642e4",
|
||||
"https://deno.land/std@0.105.0/path/_util.ts": "2e06a3b9e79beaf62687196bd4b60a4c391d862cfa007a20fc3a39f778ba073b",
|
||||
"https://deno.land/std@0.105.0/path/common.ts": "eaf03d08b569e8a87e674e4e265e099f237472b6fd135b3cbeae5827035ea14a",
|
||||
"https://deno.land/std@0.105.0/path/glob.ts": "3b84af55c53febacf6afe214c095624b22a56b6f57d7312157479cc783a0de65",
|
||||
"https://deno.land/std@0.105.0/path/mod.ts": "4465dc494f271b02569edbb4a18d727063b5dbd6ed84283ff906260970a15d12",
|
||||
"https://deno.land/std@0.105.0/path/posix.ts": "b81974c768d298f8dcd2c720229639b3803ca4a241fa9a355c762fa2bc5ef0c1",
|
||||
"https://deno.land/std@0.105.0/path/separator.ts": "8fdcf289b1b76fd726a508f57d3370ca029ae6976fcde5044007f062e643ff1c",
|
||||
"https://deno.land/std@0.105.0/path/win32.ts": "f4a3d4a3f2c9fe894da046d5eac48b5e789a0ebec5152b2c0985efe96a9f7ae1",
|
||||
"https://deno.land/x/dirname@1.1.2/mod.ts": "4029ca6b49da58d262d65f826ba9b3a89cc0b92a94c7220d5feb7bd34e498a54",
|
||||
"https://deno.land/x/dirname@1.1.2/types.ts": "c1ed1667545bc4b1d69bdb2fc26a5fa8edae3a56e3081209c16a408a322a2319",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/_util/assert.ts": "e1f76e77c5ccb5a8e0dbbbe6cce3a56d2556c8cb5a9a8802fc9565af72462149",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/_constants.ts": "aba480c4a2c098b6374fdd5951fea13ecc8aaaf8b8aa4dae1871baa50243d676",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/_interface.ts": "67b276380d297a7cedc3c17f7a0bf122edcfc96a3e1f69de06f379d85ba0e2c0",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/_util.ts": "7820a788b35c26dfc27ff329df12507fc0553ae92727009597046f6cf856b4fa",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/common.ts": "e4ec66a7416d56f60331b66e27a8a4f08c7b1cf48e350271cb69754a01cf5c04",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/glob.ts": "54fea22f0f47dee07399d22e18a34a84eaf4b8a3771bbed96db43bbec71ef237",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/mod.ts": "6de8885c2534757097818e302becd1cefcbc4c28ac022cc279e612ee04e8cfd1",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/posix.ts": "7c2539b5d9e22b47f02ccc5b6ef11e3975a5c60f49d2241271eaa5936e6082a0",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/separator.ts": "9dd15d46ff84a16e13554f56af7fee1f85f8d0f379efbbe60ac066a60561f036",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/win32.ts": "47114c941681ecbabab4ec355cb41d525fb5a14175cc47a5c76fdc5eaee2685a"
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ pub mod registry;
|
|||
|
||||
pub mod list;
|
||||
pub mod map;
|
||||
mod pool;
|
||||
pub mod text;
|
||||
|
||||
#[cfg_attr(feature = "test_utils", derive(arbitrary::Arbitrary))]
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
// TODO: refactor, extract common code with text
|
||||
use std::{
|
||||
ops::Range,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use rle::{
|
||||
rle_tree::{tree_trait::CumulateTreeTrait, HeapMode},
|
||||
|
@ -12,6 +9,7 @@ use rle::{
|
|||
use crate::{
|
||||
container::{
|
||||
list::list_op::ListOp,
|
||||
pool,
|
||||
registry::{ContainerInstance, ContainerWrapper},
|
||||
text::{
|
||||
text_content::{ListSlice, SliceRange},
|
||||
|
@ -30,45 +28,15 @@ use crate::{
|
|||
pub struct ListContainer {
|
||||
id: ContainerID,
|
||||
state: RleTree<SliceRange, CumulateTreeTrait<SliceRange, 8, HeapMode>>,
|
||||
raw_data: Pool,
|
||||
raw_data: pool::Pool,
|
||||
tracker: Tracker,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Pool(Vec<LoroValue>);
|
||||
|
||||
impl Pool {
|
||||
#[inline(always)]
|
||||
pub fn alloc<V: Into<LoroValue>>(&mut self, s: V) -> Range<u32> {
|
||||
self.0.push(s.into());
|
||||
(self.0.len() - 1) as u32..self.0.len() as u32
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn alloc_arr(&mut self, values: Vec<LoroValue>) -> Range<u32> {
|
||||
let start = self.0.len() as u32;
|
||||
for v in values {
|
||||
self.0.push(v);
|
||||
}
|
||||
start..self.0.len() as u32
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn slice(&self, range: &Range<u32>) -> &[LoroValue] {
|
||||
&self.0[range.start as usize..range.end as usize]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl ListContainer {
|
||||
pub(crate) fn new(id: ContainerID) -> Self {
|
||||
Self {
|
||||
id,
|
||||
raw_data: Pool::default(),
|
||||
raw_data: pool::Pool::default(),
|
||||
tracker: Tracker::new(Default::default(), 0),
|
||||
state: Default::default(),
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use super::super::pool::Pool;
|
||||
use fxhash::FxHashMap;
|
||||
|
||||
use crate::{
|
||||
|
@ -25,6 +26,7 @@ use super::MapSet;
|
|||
pub struct MapContainer {
|
||||
id: ContainerID,
|
||||
state: FxHashMap<InternalString, ValueSlot>,
|
||||
pool: Pool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -40,6 +42,7 @@ impl MapContainer {
|
|||
MapContainer {
|
||||
id,
|
||||
state: FxHashMap::default(),
|
||||
pool: Pool::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +53,8 @@ impl MapContainer {
|
|||
value: V,
|
||||
) {
|
||||
let value = value.into();
|
||||
let value_index = self.pool.alloc(value).start as i32;
|
||||
let value = LoroValue::I32(value_index);
|
||||
let self_id = &self.id;
|
||||
let m = ctx.log_store();
|
||||
let mut store = m.write().unwrap();
|
||||
|
@ -85,6 +90,8 @@ impl MapContainer {
|
|||
let mut store = m.write().unwrap();
|
||||
let client_id = store.this_client_id;
|
||||
let container_id = store.create_container(obj);
|
||||
let value_index = self.pool.alloc(container_id.clone()).start as i32;
|
||||
let value = LoroValue::I32(value_index);
|
||||
// TODO: store this value?
|
||||
let id = store.next_id_for(client_id);
|
||||
let container = store.get_container_idx(self_id).unwrap();
|
||||
|
@ -98,16 +105,10 @@ impl MapContainer {
|
|||
container,
|
||||
content: Content::Map(MapSet {
|
||||
key: key.clone(),
|
||||
value: container_id.clone().into(),
|
||||
value: value.clone(),
|
||||
}),
|
||||
}]);
|
||||
self.state.insert(
|
||||
key,
|
||||
ValueSlot {
|
||||
value: LoroValue::Unresolved(Box::new(container_id.clone())),
|
||||
order,
|
||||
},
|
||||
);
|
||||
self.state.insert(key, ValueSlot { value, order });
|
||||
container_id
|
||||
}
|
||||
|
||||
|
@ -130,14 +131,16 @@ impl Container for MapContainer {
|
|||
fn get_value(&self) -> LoroValue {
|
||||
let mut map = FxHashMap::default();
|
||||
for (key, value) in self.state.iter() {
|
||||
if let Some(container_id) = value.value.as_unresolved() {
|
||||
let index = *value.value.as_i32().unwrap() as u32;
|
||||
let value = self.pool.slice(&(index..index + 1))[0].clone();
|
||||
if let Some(container_id) = value.as_unresolved() {
|
||||
map.insert(
|
||||
key.to_string(),
|
||||
// TODO: make a from
|
||||
LoroValue::Unresolved(container_id.clone()),
|
||||
);
|
||||
} else {
|
||||
map.insert(key.to_string(), value.value.clone());
|
||||
map.insert(key.to_string(), value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,9 +149,23 @@ impl Container for MapContainer {
|
|||
|
||||
fn tracker_checkout(&mut self, _vv: &crate::version::VersionVector) {}
|
||||
|
||||
fn to_export(&mut self, _op: &mut RemoteOp, _gc: bool) {}
|
||||
fn to_export(&mut self, op: &mut RemoteOp, _gc: bool) {
|
||||
for content in op.contents.iter_mut() {
|
||||
if let Some(set) = content.as_map_mut() {
|
||||
let index = *set.value.as_i32().unwrap() as u32;
|
||||
set.value = self.pool.slice(&(index..index + 1))[0].clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_import(&mut self, _op: &mut RemoteOp) {}
|
||||
fn to_import(&mut self, op: &mut RemoteOp) {
|
||||
for content in op.contents.iter_mut() {
|
||||
if let Some(set) = content.as_map_mut() {
|
||||
let index = self.pool.alloc(std::mem::take(&mut set.value));
|
||||
set.value = LoroValue::I32(index.start as i32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_state_directly(&mut self, op: &RichOp) {
|
||||
let content = op.get_sliced().content;
|
||||
|
|
33
crates/loro-core/src/container/pool.rs
Normal file
33
crates/loro-core/src/container/pool.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
use std::ops::Range;
|
||||
|
||||
use crate::value::LoroValue;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct Pool(Vec<LoroValue>);
|
||||
|
||||
impl Pool {
|
||||
#[inline(always)]
|
||||
pub fn alloc<V: Into<LoroValue>>(&mut self, s: V) -> Range<u32> {
|
||||
self.0.push(s.into());
|
||||
(self.0.len() - 1) as u32..self.0.len() as u32
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn alloc_arr(&mut self, values: Vec<LoroValue>) -> Range<u32> {
|
||||
let start = self.0.len() as u32;
|
||||
for v in values {
|
||||
self.0.push(v);
|
||||
}
|
||||
start..self.0.len() as u32
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn slice(&self, range: &Range<u32>) -> &[LoroValue] {
|
||||
&self.0[range.start as usize..range.end as usize]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
|
@ -170,7 +170,7 @@ impl Sliceable for YSpan {
|
|||
|
||||
impl InsertContentTrait for YSpan {
|
||||
fn id(&self) -> ContentType {
|
||||
ContentType::Text
|
||||
ContentType::List
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ pub mod test {
|
|||
));
|
||||
assert_eq!(vec.merged_len(), 1);
|
||||
let merged = vec.get_merged(0).unwrap();
|
||||
assert_eq!(merged.content.id(), ContentType::Text);
|
||||
assert_eq!(merged.content.id(), ContentType::List);
|
||||
let text_content = merged.content.as_dyn().unwrap();
|
||||
dbg!(&merged);
|
||||
assert_eq!(text_content.content_len(), 2);
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::container::{list::list_op::ListOp, map::MapSet};
|
|||
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
|
||||
pub enum ContentType {
|
||||
/// See [`crate::container::text::TextContent`]
|
||||
Text,
|
||||
List,
|
||||
/// See [`crate::container::map::MapInsertContent`]
|
||||
Map,
|
||||
/// Users can define their own content types.
|
||||
|
@ -36,7 +36,7 @@ impl Content {
|
|||
pub fn id(&self) -> ContentType {
|
||||
match self {
|
||||
Self::Map(_) => ContentType::Map,
|
||||
Self::List(_) => ContentType::Text,
|
||||
Self::List(_) => ContentType::List,
|
||||
Self::Dyn(arg0) => arg0.id(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"test-all": "deno task test & deno task quick-fuzz",
|
||||
"test-prop": "RUSTFLAGS='--cfg=proptest' cargo nextest run --features=test_utils",
|
||||
"check": "cargo clippy --all-features",
|
||||
"quick-fuzz": "cd crates/loro-core && just quick-fuzz",
|
||||
"quick-fuzz": "cd crates/loro-core && deno task quick-fuzz",
|
||||
"fix": "cargo clippy --fix --features=test_utils",
|
||||
"vet": "cargo vet"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue