mirror of
https://github.com/loro-dev/loro.git
synced 2025-02-06 04:19:34 +00:00
refactor: map delete value
This commit is contained in:
parent
fb64ff5422
commit
3f3fcc11f3
11 changed files with 103 additions and 63 deletions
|
@ -10,7 +10,7 @@ use crate::{
|
|||
container::{
|
||||
idx::ContainerIdx,
|
||||
list::list_op::{InnerListOp, ListOp},
|
||||
map::InnerMapSet,
|
||||
map::{InnerMapSet, MapSet},
|
||||
text::text_content::SliceRange,
|
||||
ContainerID,
|
||||
},
|
||||
|
@ -81,15 +81,16 @@ impl<'a> OpConverter<'a> {
|
|||
};
|
||||
|
||||
match content {
|
||||
crate::op::RawOpContent::Map(map) => {
|
||||
let value = _alloc_value(&mut self.values, map.value) as u32;
|
||||
crate::op::RawOpContent::Map(MapSet { key, value }) => {
|
||||
let value = if let Some(value) = value {
|
||||
Some(_alloc_value(&mut self.values, value) as u32)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Op {
|
||||
counter,
|
||||
container,
|
||||
content: crate::op::InnerContent::Map(InnerMapSet {
|
||||
key: map.key,
|
||||
value,
|
||||
}),
|
||||
content: crate::op::InnerContent::Map(InnerMapSet { key, value }),
|
||||
}
|
||||
}
|
||||
crate::op::RawOpContent::List(list) => match list {
|
||||
|
@ -291,15 +292,16 @@ impl SharedArena {
|
|||
container: ContainerIdx,
|
||||
) -> Op {
|
||||
match content {
|
||||
crate::op::RawOpContent::Map(map) => {
|
||||
let value = self.alloc_value(map.value) as u32;
|
||||
crate::op::RawOpContent::Map(MapSet { key, value }) => {
|
||||
let value = if let Some(value) = value {
|
||||
Some(self.alloc_value(value) as u32)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Op {
|
||||
counter,
|
||||
container,
|
||||
content: crate::op::InnerContent::Map(InnerMapSet {
|
||||
key: map.key,
|
||||
value,
|
||||
}),
|
||||
content: crate::op::InnerContent::Map(InnerMapSet { key, value }),
|
||||
}
|
||||
}
|
||||
crate::op::RawOpContent::List(list) => match list {
|
||||
|
|
|
@ -7,14 +7,15 @@ use crate::{InternalString, LoroValue};
|
|||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MapSet {
|
||||
pub(crate) key: InternalString,
|
||||
pub(crate) value: LoroValue,
|
||||
// the key is deleted if value is None
|
||||
pub(crate) value: Option<LoroValue>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct InnerMapSet {
|
||||
pub(crate) key: InternalString,
|
||||
// FIXME: how to set None?
|
||||
pub(crate) value: u32,
|
||||
// the key is deleted if value is None
|
||||
pub(crate) value: Option<u32>,
|
||||
}
|
||||
|
||||
impl Mergable for MapSet {}
|
||||
|
@ -50,9 +51,9 @@ mod test {
|
|||
fn fix_fields_order() {
|
||||
let map_set = vec![MapSet {
|
||||
key: "key".to_string().into(),
|
||||
value: "value".to_string().into(),
|
||||
value: Some("value".to_string().into()),
|
||||
}];
|
||||
let map_set_buf = vec![1, 3, 107, 101, 121, 4, 5, 118, 97, 108, 117, 101];
|
||||
let map_set_buf = vec![1, 3, 107, 101, 121, 1, 4, 5, 118, 97, 108, 117, 101];
|
||||
assert_eq!(
|
||||
postcard::from_bytes::<Vec<MapSet>>(&map_set_buf).unwrap(),
|
||||
map_set
|
||||
|
|
|
@ -293,7 +293,7 @@ impl DiffCalculatorTrait for MapDiffCalculator {
|
|||
for (key, value) in changed {
|
||||
let value = value
|
||||
.map(|v| {
|
||||
let value = oplog.arena.get_value(v.value as usize);
|
||||
let value = v.value.map(|v| oplog.arena.get_value(v as usize)).flatten();
|
||||
MapValue {
|
||||
counter: v.counter,
|
||||
value,
|
||||
|
@ -317,7 +317,7 @@ struct CompactMapValue {
|
|||
lamport: Lamport,
|
||||
peer: PeerID,
|
||||
counter: Counter,
|
||||
value: u32,
|
||||
value: Option<u32>,
|
||||
}
|
||||
|
||||
impl HasId for CompactMapValue {
|
||||
|
|
|
@ -51,7 +51,7 @@ struct OpEncoding {
|
|||
/// key index or insert/delete pos
|
||||
#[columnar(strategy = "DeltaRle")]
|
||||
prop: usize,
|
||||
value: LoroValue,
|
||||
value: Option<LoroValue>,
|
||||
}
|
||||
|
||||
#[columnar(vec, ser, de, iterable)]
|
||||
|
@ -169,16 +169,16 @@ pub(super) fn encode_oplog_changes(oplog: &OpLog, vv: &VersionVector) -> Vec<u8>
|
|||
ListOp::Insert { slice, pos } => (
|
||||
pos,
|
||||
// TODO: perf may be optimized by using borrow type instead
|
||||
match slice {
|
||||
Some(match slice {
|
||||
ListSlice::RawData(v) => LoroValue::List(Arc::new(v.to_vec())),
|
||||
ListSlice::RawStr {
|
||||
str,
|
||||
unicode_len: _,
|
||||
} => LoroValue::String(Arc::new(str.to_string())),
|
||||
},
|
||||
}),
|
||||
),
|
||||
ListOp::Delete(span) => {
|
||||
(span.pos as usize, LoroValue::I32(span.len as i32))
|
||||
(span.pos as usize, Some(LoroValue::I32(span.len as i32)))
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -270,6 +270,7 @@ pub(super) fn decode_changes_to_inner_format_oplog(
|
|||
}
|
||||
ContainerType::List | ContainerType::Text => {
|
||||
let pos = prop;
|
||||
let value = value.unwrap();
|
||||
let list_op = match value {
|
||||
LoroValue::I32(len) => ListOp::Delete(DeleteSpan {
|
||||
pos: pos as isize,
|
||||
|
|
|
@ -110,7 +110,7 @@ struct DocEncoding<'a> {
|
|||
#[columnar(borrow)]
|
||||
root_containers: VarZeroVec<'a, RootContainerULE, Index32>,
|
||||
start_counter: Vec<Counter>,
|
||||
values: Vec<LoroValue>,
|
||||
values: Vec<Option<LoroValue>>,
|
||||
clients: Vec<PeerID>,
|
||||
keys: Vec<InternalString>,
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ pub fn encode_oplog_v2(oplog: &OpLog, vv: &VersionVector) -> Vec<u8> {
|
|||
let mut len = 0;
|
||||
match slice {
|
||||
ListSlice::RawData(v) => {
|
||||
values.push(LoroValue::List(Arc::new(v.to_vec())));
|
||||
values.push(Some(LoroValue::List(Arc::new(v.to_vec()))));
|
||||
}
|
||||
ListSlice::RawStr {
|
||||
str,
|
||||
|
@ -451,7 +451,7 @@ pub fn decode_oplog_v2(oplog: &mut OpLog, input: &[u8]) -> Result<(), LoroError>
|
|||
})
|
||||
}
|
||||
ContainerType::List => {
|
||||
let value = value_iter.next().unwrap();
|
||||
let value = value_iter.next().flatten().unwrap();
|
||||
RawOpContent::List(ListOp::Insert {
|
||||
slice: ListSlice::RawData(Cow::Owned(
|
||||
match Arc::try_unwrap(value.into_list().unwrap()) {
|
||||
|
|
|
@ -527,7 +527,7 @@ impl MapHandler {
|
|||
self.container_idx,
|
||||
crate::op::RawOpContent::Map(crate::container::map::MapSet {
|
||||
key: key.into(),
|
||||
value,
|
||||
value: Some(value),
|
||||
}),
|
||||
None,
|
||||
&self.state,
|
||||
|
@ -548,7 +548,7 @@ impl MapHandler {
|
|||
self.container_idx,
|
||||
crate::op::RawOpContent::Map(crate::container::map::MapSet {
|
||||
key: key.into(),
|
||||
value: LoroValue::Container(container_id),
|
||||
value: Some(LoroValue::Container(container_id)),
|
||||
}),
|
||||
None,
|
||||
&self.state,
|
||||
|
@ -562,8 +562,7 @@ impl MapHandler {
|
|||
self.container_idx,
|
||||
crate::op::RawOpContent::Map(crate::container::map::MapSet {
|
||||
key: key.into(),
|
||||
// TODO: use another special value to delete?
|
||||
value: LoroValue::Null,
|
||||
value: None,
|
||||
}),
|
||||
None,
|
||||
&self.state,
|
||||
|
|
|
@ -198,10 +198,10 @@ mod test {
|
|||
RawOpContent::List(ListOp::Delete(DeleteSpan { pos: 0, len: 1 })),
|
||||
RawOpContent::Map(MapSet {
|
||||
key: "a".to_string().into(),
|
||||
value: "b".to_string().into(),
|
||||
value: Some("b".to_string().into()),
|
||||
}),
|
||||
];
|
||||
let remote_content_buf = vec![2, 1, 1, 0, 2, 0, 1, 97, 4, 1, 98];
|
||||
let remote_content_buf = vec![2, 1, 1, 0, 2, 0, 1, 97, 1, 4, 1, 98];
|
||||
assert_eq!(
|
||||
postcard::from_bytes::<Vec<RawOpContent>>(&remote_content_buf).unwrap(),
|
||||
remote_content
|
||||
|
|
|
@ -382,10 +382,13 @@ impl OpLog {
|
|||
}
|
||||
},
|
||||
crate::op::InnerContent::Map(map) => {
|
||||
let value = self.arena.get_value(map.value as usize);
|
||||
let value = map
|
||||
.value
|
||||
.map(|v| self.arena.get_value(v as usize))
|
||||
.flatten();
|
||||
contents.push(RawOpContent::Map(crate::container::map::MapSet {
|
||||
key: map.key.clone(),
|
||||
value: value.unwrap_or(crate::LoroValue::Null), // TODO: decide map delete value
|
||||
value,
|
||||
}))
|
||||
}
|
||||
};
|
||||
|
|
|
@ -145,7 +145,7 @@ pub fn decode_oplog(
|
|||
id,
|
||||
InnerContent::Map(InnerMapSet {
|
||||
key: (&*keys[key]).into(),
|
||||
value: value_idx_plus_one - 1,
|
||||
value: value_idx_plus_one.map(|v| v - 1),
|
||||
}),
|
||||
container_idx,
|
||||
),
|
||||
|
@ -326,14 +326,26 @@ struct EncodedSnapshotOp {
|
|||
// List: 0 | value index
|
||||
// Map: value index
|
||||
#[columnar(strategy = "DeltaRle")]
|
||||
value: usize,
|
||||
value: isize,
|
||||
}
|
||||
|
||||
enum SnapshotOp {
|
||||
TextInsert { pos: usize, len: usize },
|
||||
ListInsert { pos: usize, value_idx: u32 },
|
||||
TextOrListDelete { pos: usize, len: isize },
|
||||
Map { key: usize, value_idx_plus_one: u32 },
|
||||
TextInsert {
|
||||
pos: usize,
|
||||
len: usize,
|
||||
},
|
||||
ListInsert {
|
||||
pos: usize,
|
||||
value_idx: u32,
|
||||
},
|
||||
TextOrListDelete {
|
||||
pos: usize,
|
||||
len: isize,
|
||||
},
|
||||
Map {
|
||||
key: usize,
|
||||
value_idx_plus_one: Option<u32>,
|
||||
},
|
||||
}
|
||||
|
||||
impl EncodedSnapshotOp {
|
||||
|
@ -366,9 +378,14 @@ impl EncodedSnapshotOp {
|
|||
}
|
||||
|
||||
pub fn get_map(&self) -> SnapshotOp {
|
||||
let value_idx_plus_one = if self.value < 0 {
|
||||
None
|
||||
} else {
|
||||
Some(self.value as u32)
|
||||
};
|
||||
SnapshotOp::Map {
|
||||
key: self.prop,
|
||||
value_idx_plus_one: self.value as u32,
|
||||
value_idx_plus_one,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,7 +399,7 @@ impl EncodedSnapshotOp {
|
|||
prop: pos,
|
||||
len: 0,
|
||||
is_del: false,
|
||||
value: start as usize,
|
||||
value: start as isize,
|
||||
},
|
||||
SnapshotOp::TextOrListDelete { pos, len } => Self {
|
||||
container,
|
||||
|
@ -394,13 +411,16 @@ impl EncodedSnapshotOp {
|
|||
SnapshotOp::Map {
|
||||
key,
|
||||
value_idx_plus_one: value,
|
||||
} => Self {
|
||||
container,
|
||||
prop: key,
|
||||
len: 0,
|
||||
is_del: false,
|
||||
value: value as usize,
|
||||
},
|
||||
} => {
|
||||
let value = if let Some(v) = value { v as isize } else { -1 };
|
||||
Self {
|
||||
container,
|
||||
prop: key,
|
||||
len: 0,
|
||||
is_del: false,
|
||||
value,
|
||||
}
|
||||
}
|
||||
SnapshotOp::TextInsert { pos, len } => Self {
|
||||
container,
|
||||
prop: pos,
|
||||
|
@ -666,17 +686,19 @@ fn encode_oplog(oplog: &OpLog, state_ref: Option<PreEncodedState>) -> FinalPhase
|
|||
},
|
||||
InnerContent::Map(map) => {
|
||||
let key = record_key(&map.key);
|
||||
let value = oplog.arena.get_value(map.value as usize);
|
||||
// FIXME: delete in map
|
||||
let value = map
|
||||
.value
|
||||
.map(|v| oplog.arena.get_value(v as usize))
|
||||
.flatten();
|
||||
let value = if let Some(value) = value {
|
||||
record_value(&value) + 1
|
||||
Some((record_value(&value) + 1) as u32)
|
||||
} else {
|
||||
0
|
||||
None
|
||||
};
|
||||
encoded_ops.push(EncodedSnapshotOp::from(
|
||||
SnapshotOp::Map {
|
||||
key,
|
||||
value_idx_plus_one: value as u32,
|
||||
value_idx_plus_one: value,
|
||||
},
|
||||
op.container.to_index(),
|
||||
));
|
||||
|
|
|
@ -5,7 +5,7 @@ use loro_common::ContainerID;
|
|||
|
||||
use crate::{
|
||||
arena::SharedArena,
|
||||
container::idx::ContainerIdx,
|
||||
container::{idx::ContainerIdx, map::MapSet},
|
||||
delta::MapValue,
|
||||
event::{Diff, Index},
|
||||
op::{RawOp, RawOpContent},
|
||||
|
@ -39,18 +39,30 @@ impl ContainerState for MapState {
|
|||
|
||||
fn apply_op(&mut self, op: RawOp, arena: &SharedArena) {
|
||||
match op.content {
|
||||
RawOpContent::Map(map) => {
|
||||
if map.value.is_container() {
|
||||
let idx = arena.register_container(map.value.as_container().unwrap());
|
||||
RawOpContent::Map(MapSet { key, value }) => {
|
||||
if value.is_none() {
|
||||
self.insert(
|
||||
key,
|
||||
MapValue {
|
||||
lamport: (op.lamport, op.id.peer),
|
||||
counter: op.id.counter,
|
||||
value: None,
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
let value = value.unwrap();
|
||||
if value.is_container() {
|
||||
let idx = arena.register_container(value.as_container().unwrap());
|
||||
arena.set_parent(idx, Some(self.idx));
|
||||
}
|
||||
|
||||
self.insert(
|
||||
map.key,
|
||||
key,
|
||||
MapValue {
|
||||
lamport: (op.lamport, op.id.peer),
|
||||
counter: op.id.counter,
|
||||
value: Some(map.value),
|
||||
value: Some(value),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -342,13 +342,13 @@ fn change_to_diff(
|
|||
),
|
||||
},
|
||||
crate::op::InnerContent::Map(map) => {
|
||||
let value = arena.get_value(map.value as usize).unwrap();
|
||||
let value = map.value.map(|v| arena.get_value(v as usize)).flatten();
|
||||
let mut updated: FxHashMap<_, _> = Default::default();
|
||||
updated.insert(
|
||||
map.key.clone(),
|
||||
MapValue {
|
||||
counter,
|
||||
value: Some(value),
|
||||
value,
|
||||
lamport: (lamport, peer),
|
||||
},
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue