mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-23 13:39:12 +00:00
refactor: add inner content
This commit is contained in:
parent
8dba7d1e3a
commit
7295e1c613
12 changed files with 81 additions and 60 deletions
|
@ -19,7 +19,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::Context,
|
context::Context,
|
||||||
id::{Counter, ID},
|
id::{Counter, ID},
|
||||||
op::{Content, Op, RemoteOp, RichOp},
|
op::{Op, RemoteContent, RemoteOp, RichOp},
|
||||||
value::LoroValue,
|
value::LoroValue,
|
||||||
version::IdSpanVector,
|
version::IdSpanVector,
|
||||||
};
|
};
|
||||||
|
@ -54,7 +54,7 @@ impl ListContainer {
|
||||||
self.state.insert(pos, slice.clone().into());
|
self.state.insert(pos, slice.clone().into());
|
||||||
let op = Op::new(
|
let op = Op::new(
|
||||||
id,
|
id,
|
||||||
Content::List(ListOp::Insert {
|
RemoteContent::List(ListOp::Insert {
|
||||||
slice: slice.into(),
|
slice: slice.into(),
|
||||||
pos,
|
pos,
|
||||||
}),
|
}),
|
||||||
|
@ -76,7 +76,7 @@ impl ListContainer {
|
||||||
self.state.insert(pos, slice.clone().into());
|
self.state.insert(pos, slice.clone().into());
|
||||||
let op = Op::new(
|
let op = Op::new(
|
||||||
id,
|
id,
|
||||||
Content::List(ListOp::Insert {
|
RemoteContent::List(ListOp::Insert {
|
||||||
slice: slice.into(),
|
slice: slice.into(),
|
||||||
pos,
|
pos,
|
||||||
}),
|
}),
|
||||||
|
@ -101,7 +101,7 @@ impl ListContainer {
|
||||||
let id = store.next_id();
|
let id = store.next_id();
|
||||||
let op = Op::new(
|
let op = Op::new(
|
||||||
id,
|
id,
|
||||||
Content::List(ListOp::new_del(pos, len)),
|
RemoteContent::List(ListOp::new_del(pos, len)),
|
||||||
store.get_or_create_container_idx(&self.id),
|
store.get_or_create_container_idx(&self.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ impl Container for ListContainer {
|
||||||
|
|
||||||
fn update_state_directly(&mut self, op: &RichOp) {
|
fn update_state_directly(&mut self, op: &RichOp) {
|
||||||
match &op.get_sliced().content {
|
match &op.get_sliced().content {
|
||||||
Content::List(op) => match op {
|
RemoteContent::List(op) => match op {
|
||||||
ListOp::Insert { slice, pos } => {
|
ListOp::Insert { slice, pos } => {
|
||||||
self.state.insert(*pos, slice.as_slice().unwrap().clone())
|
self.state.insert(*pos, slice.as_slice().unwrap().clone())
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::ops::Range;
|
||||||
use enum_as_inner::EnumAsInner;
|
use enum_as_inner::EnumAsInner;
|
||||||
use rle::{HasLength, Mergable, Sliceable};
|
use rle::{HasLength, Mergable, Sliceable};
|
||||||
|
|
||||||
use crate::container::text::text_content::ListSlice;
|
use crate::container::text::text_content::{ListSlice, SliceRange};
|
||||||
|
|
||||||
#[derive(EnumAsInner, Debug, Clone)]
|
#[derive(EnumAsInner, Debug, Clone)]
|
||||||
pub enum ListOp {
|
pub enum ListOp {
|
||||||
|
@ -11,6 +11,12 @@ pub enum ListOp {
|
||||||
Delete(DeleteSpan),
|
Delete(DeleteSpan),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(EnumAsInner, Debug, Clone)]
|
||||||
|
pub enum InnerListOp {
|
||||||
|
Insert { slice: SliceRange, pos: usize },
|
||||||
|
Delete(DeleteSpan),
|
||||||
|
}
|
||||||
|
|
||||||
/// `len` can be negative so that we can merge text deletions efficiently.
|
/// `len` can be negative so that we can merge text deletions efficiently.
|
||||||
/// It looks like [crate::span::CounterSpan], but how should they merge ([Mergable] impl) and slice ([Sliceable] impl) are very different
|
/// It looks like [crate::span::CounterSpan], but how should they merge ([Mergable] impl) and slice ([Sliceable] impl) are very different
|
||||||
///
|
///
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::Context,
|
context::Context,
|
||||||
op::RemoteOp,
|
op::RemoteOp,
|
||||||
op::{Content, Op, RichOp},
|
op::{Op, RemoteContent, RichOp},
|
||||||
span::HasLamport,
|
span::HasLamport,
|
||||||
value::LoroValue,
|
value::LoroValue,
|
||||||
version::{IdSpanVector, TotalOrderStamp},
|
version::{IdSpanVector, TotalOrderStamp},
|
||||||
|
@ -70,7 +70,7 @@ impl MapContainer {
|
||||||
store.append_local_ops(&[Op {
|
store.append_local_ops(&[Op {
|
||||||
counter: id.counter,
|
counter: id.counter,
|
||||||
container,
|
container,
|
||||||
content: Content::Map(MapSet {
|
content: RemoteContent::Map(MapSet {
|
||||||
key: key.clone(),
|
key: key.clone(),
|
||||||
value: value.clone(),
|
value: value.clone(),
|
||||||
}),
|
}),
|
||||||
|
@ -103,7 +103,7 @@ impl MapContainer {
|
||||||
store.append_local_ops(&[Op {
|
store.append_local_ops(&[Op {
|
||||||
counter: id.counter,
|
counter: id.counter,
|
||||||
container,
|
container,
|
||||||
content: Content::Map(MapSet {
|
content: RemoteContent::Map(MapSet {
|
||||||
key: key.clone(),
|
key: key.clone(),
|
||||||
value: value.clone(),
|
value: value.clone(),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -2,13 +2,18 @@ use rle::{HasLength, Mergable, Sliceable};
|
||||||
|
|
||||||
use crate::{ContentType, InsertContentTrait, InternalString, LoroValue};
|
use crate::{ContentType, InsertContentTrait, InternalString, LoroValue};
|
||||||
|
|
||||||
// TODO: use imported and exported format to save the space
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct MapSet {
|
pub struct MapSet {
|
||||||
pub(crate) key: InternalString,
|
pub(crate) key: InternalString,
|
||||||
pub(crate) value: LoroValue,
|
pub(crate) value: LoroValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct InnerMapSet {
|
||||||
|
pub(crate) key: InternalString,
|
||||||
|
pub(crate) value: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl Mergable for MapSet {}
|
impl Mergable for MapSet {}
|
||||||
impl Sliceable for MapSet {
|
impl Sliceable for MapSet {
|
||||||
fn slice(&self, from: usize, to: usize) -> Self {
|
fn slice(&self, from: usize, to: usize) -> Self {
|
||||||
|
|
|
@ -4,4 +4,4 @@ mod tests;
|
||||||
|
|
||||||
pub use map_container::Map;
|
pub use map_container::Map;
|
||||||
pub(crate) use map_container::MapContainer;
|
pub(crate) use map_container::MapContainer;
|
||||||
pub(crate) use map_content::MapSet;
|
pub(crate) use map_content::{InnerMapSet, MapSet};
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
context::Context,
|
context::Context,
|
||||||
debug_log,
|
debug_log,
|
||||||
id::{Counter, ID},
|
id::{Counter, ID},
|
||||||
op::{Content, Op, RemoteOp, RichOp},
|
op::{Op, RemoteContent, RemoteOp, RichOp},
|
||||||
value::LoroValue,
|
value::LoroValue,
|
||||||
version::IdSpanVector,
|
version::IdSpanVector,
|
||||||
};
|
};
|
||||||
|
@ -59,7 +59,7 @@ impl TextContainer {
|
||||||
self.state.insert(pos, slice.clone().into());
|
self.state.insert(pos, slice.clone().into());
|
||||||
let op = Op::new(
|
let op = Op::new(
|
||||||
id,
|
id,
|
||||||
Content::List(ListOp::Insert {
|
RemoteContent::List(ListOp::Insert {
|
||||||
slice: slice.into(),
|
slice: slice.into(),
|
||||||
pos,
|
pos,
|
||||||
}),
|
}),
|
||||||
|
@ -84,7 +84,7 @@ impl TextContainer {
|
||||||
let id = store.next_id();
|
let id = store.next_id();
|
||||||
let op = Op::new(
|
let op = Op::new(
|
||||||
id,
|
id,
|
||||||
Content::List(ListOp::new_del(pos, len)),
|
RemoteContent::List(ListOp::new_del(pos, len)),
|
||||||
store.get_or_create_container_idx(&self.id),
|
store.get_or_create_container_idx(&self.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ impl Container for TextContainer {
|
||||||
.update_aliveness(self.state.iter().map(|x| x.as_ref().0.clone()))
|
.update_aliveness(self.state.iter().map(|x| x.as_ref().0.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut contents: RleVec<[Content; 1]> = RleVec::new();
|
let mut contents: RleVec<[RemoteContent; 1]> = RleVec::new();
|
||||||
for content in op.contents.iter_mut() {
|
for content in op.contents.iter_mut() {
|
||||||
if let Some((slice, pos)) = content.as_list_mut().and_then(|x| x.as_insert_mut()) {
|
if let Some((slice, pos)) = content.as_list_mut().and_then(|x| x.as_insert_mut()) {
|
||||||
match slice {
|
match slice {
|
||||||
|
@ -158,13 +158,13 @@ impl Container for TextContainer {
|
||||||
for span in self.raw_str.get_aliveness(&r.0) {
|
for span in self.raw_str.get_aliveness(&r.0) {
|
||||||
match span {
|
match span {
|
||||||
Alive::True(span) => {
|
Alive::True(span) => {
|
||||||
contents.push(Content::List(ListOp::Insert {
|
contents.push(RemoteContent::List(ListOp::Insert {
|
||||||
slice: ListSlice::RawStr(s[start..start + span].into()),
|
slice: ListSlice::RawStr(s[start..start + span].into()),
|
||||||
pos: pos_start,
|
pos: pos_start,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Alive::False(span) => {
|
Alive::False(span) => {
|
||||||
let v = Content::List(ListOp::Insert {
|
let v = RemoteContent::List(ListOp::Insert {
|
||||||
slice: ListSlice::Unknown(span),
|
slice: ListSlice::Unknown(span),
|
||||||
pos: pos_start,
|
pos: pos_start,
|
||||||
});
|
});
|
||||||
|
@ -177,14 +177,14 @@ impl Container for TextContainer {
|
||||||
}
|
}
|
||||||
assert_eq!(start, r.atom_len());
|
assert_eq!(start, r.atom_len());
|
||||||
} else {
|
} else {
|
||||||
contents.push(Content::List(ListOp::Insert {
|
contents.push(RemoteContent::List(ListOp::Insert {
|
||||||
slice: ListSlice::RawStr(s),
|
slice: ListSlice::RawStr(s),
|
||||||
pos: *pos,
|
pos: *pos,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this => {
|
this => {
|
||||||
contents.push(Content::List(ListOp::Insert {
|
contents.push(RemoteContent::List(ListOp::Insert {
|
||||||
slice: this.clone(),
|
slice: this.clone(),
|
||||||
pos: *pos,
|
pos: *pos,
|
||||||
}));
|
}));
|
||||||
|
@ -220,7 +220,7 @@ impl Container for TextContainer {
|
||||||
|
|
||||||
fn update_state_directly(&mut self, op: &RichOp) {
|
fn update_state_directly(&mut self, op: &RichOp) {
|
||||||
match &op.get_sliced().content {
|
match &op.get_sliced().content {
|
||||||
Content::List(op) => match op {
|
RemoteContent::List(op) => match op {
|
||||||
ListOp::Insert { slice, pos } => {
|
ListOp::Insert { slice, pos } => {
|
||||||
let v = match slice {
|
let v = match slice {
|
||||||
ListSlice::Slice(slice) => slice.clone(),
|
ListSlice::Slice(slice) => slice.clone(),
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
container::{list::list_op::ListOp, text::tracker::yata_impl::YataImpl},
|
container::{list::list_op::ListOp, text::tracker::yata_impl::YataImpl},
|
||||||
debug_log,
|
debug_log,
|
||||||
id::{Counter, ID},
|
id::{Counter, ID},
|
||||||
op::{Content, RichOp},
|
op::{RemoteContent, RichOp},
|
||||||
span::{HasId, HasIdSpan, IdSpan},
|
span::{HasId, HasIdSpan, IdSpan},
|
||||||
version::IdSpanVector,
|
version::IdSpanVector,
|
||||||
VersionVector,
|
VersionVector,
|
||||||
|
@ -303,7 +303,7 @@ impl Tracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// apply an operation directly to the current tracker
|
/// apply an operation directly to the current tracker
|
||||||
fn apply(&mut self, id: ID, content: &Content) {
|
fn apply(&mut self, id: ID, content: &RemoteContent) {
|
||||||
self.real_checkout();
|
self.real_checkout();
|
||||||
assert!(*self.current_vv.get(&id.client_id).unwrap_or(&0) <= id.counter);
|
assert!(*self.current_vv.get(&id.client_id).unwrap_or(&0) <= id.counter);
|
||||||
assert!(*self.all_vv.get(&id.client_id).unwrap_or(&0) <= id.counter);
|
assert!(*self.all_vv.get(&id.client_id).unwrap_or(&0) <= id.counter);
|
||||||
|
|
|
@ -192,7 +192,7 @@ impl HasLength for YSpan {
|
||||||
|
|
||||||
#[cfg(any(test, features = "test_utils"))]
|
#[cfg(any(test, features = "test_utils"))]
|
||||||
pub mod test {
|
pub mod test {
|
||||||
use crate::{container::text::text_content::ListSlice, op::Content, ContentType, Op, ID};
|
use crate::{container::text::text_content::ListSlice, op::RemoteContent, ContentType, Op, ID};
|
||||||
use rle::{HasLength, RleVecWithIndex};
|
use rle::{HasLength, RleVecWithIndex};
|
||||||
|
|
||||||
use super::YSpan;
|
use super::YSpan;
|
||||||
|
@ -202,7 +202,7 @@ pub mod test {
|
||||||
let mut vec: RleVecWithIndex<Op> = RleVecWithIndex::new();
|
let mut vec: RleVecWithIndex<Op> = RleVecWithIndex::new();
|
||||||
vec.push(Op::new(
|
vec.push(Op::new(
|
||||||
ID::new(0, 1),
|
ID::new(0, 1),
|
||||||
Content::Dyn(Box::new(YSpan {
|
RemoteContent::Dyn(Box::new(YSpan {
|
||||||
origin_left: Some(ID::new(0, 0)),
|
origin_left: Some(ID::new(0, 0)),
|
||||||
origin_right: None,
|
origin_right: None,
|
||||||
id: ID::new(0, 1),
|
id: ID::new(0, 1),
|
||||||
|
@ -213,7 +213,7 @@ pub mod test {
|
||||||
));
|
));
|
||||||
vec.push(Op::new(
|
vec.push(Op::new(
|
||||||
ID::new(0, 2),
|
ID::new(0, 2),
|
||||||
Content::Dyn(Box::new(YSpan {
|
RemoteContent::Dyn(Box::new(YSpan {
|
||||||
origin_left: Some(ID::new(0, 1)),
|
origin_left: Some(ID::new(0, 1)),
|
||||||
origin_right: None,
|
origin_right: None,
|
||||||
id: ID::new(0, 2),
|
id: ID::new(0, 2),
|
||||||
|
@ -235,7 +235,7 @@ pub mod test {
|
||||||
let mut vec: RleVecWithIndex<Op> = RleVecWithIndex::new();
|
let mut vec: RleVecWithIndex<Op> = RleVecWithIndex::new();
|
||||||
vec.push(Op::new(
|
vec.push(Op::new(
|
||||||
ID::new(0, 1),
|
ID::new(0, 1),
|
||||||
Content::Dyn(Box::new(YSpan {
|
RemoteContent::Dyn(Box::new(YSpan {
|
||||||
origin_left: Some(ID::new(0, 0)),
|
origin_left: Some(ID::new(0, 0)),
|
||||||
origin_right: None,
|
origin_right: None,
|
||||||
id: ID::new(0, 1),
|
id: ID::new(0, 1),
|
||||||
|
@ -246,7 +246,7 @@ pub mod test {
|
||||||
));
|
));
|
||||||
vec.push(Op::new(
|
vec.push(Op::new(
|
||||||
ID::new(0, 2),
|
ID::new(0, 2),
|
||||||
Content::Dyn(Box::new(YSpan {
|
RemoteContent::Dyn(Box::new(YSpan {
|
||||||
origin_left: Some(ID::new(0, 0)),
|
origin_left: Some(ID::new(0, 0)),
|
||||||
origin_right: Some(ID::new(0, 1)),
|
origin_right: Some(ID::new(0, 1)),
|
||||||
id: ID::new(0, 5),
|
id: ID::new(0, 5),
|
||||||
|
|
|
@ -20,7 +20,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
dag::remove_included_frontiers,
|
dag::remove_included_frontiers,
|
||||||
id::{ClientID, ContainerIdx, Counter, ID},
|
id::{ClientID, ContainerIdx, Counter, ID},
|
||||||
op::{Content, Op, RemoteOp},
|
op::{Op, RemoteContent, RemoteOp},
|
||||||
smstring::SmString,
|
smstring::SmString,
|
||||||
span::{HasIdSpan, HasLamportSpan},
|
span::{HasIdSpan, HasLamportSpan},
|
||||||
ContainerType, InternalString, LogStore, LoroValue, VersionVector,
|
ContainerType, InternalString, LogStore, LoroValue, VersionVector,
|
||||||
|
@ -129,7 +129,7 @@ fn encode_changes(store: &LogStore) -> Encoded {
|
||||||
for (op, container) in remote_ops.into_iter().zip(containers.into_iter()) {
|
for (op, container) in remote_ops.into_iter().zip(containers.into_iter()) {
|
||||||
for content in op.contents.into_iter() {
|
for content in op.contents.into_iter() {
|
||||||
let (prop, gc, value) = match content {
|
let (prop, gc, value) = match content {
|
||||||
crate::op::Content::Map(MapSet { key, value }) => (
|
crate::op::RemoteContent::Map(MapSet { key, value }) => (
|
||||||
*key_to_idx.entry(key.clone()).or_insert_with(|| {
|
*key_to_idx.entry(key.clone()).or_insert_with(|| {
|
||||||
keys.push(key);
|
keys.push(key);
|
||||||
keys.len() - 1
|
keys.len() - 1
|
||||||
|
@ -137,7 +137,7 @@ fn encode_changes(store: &LogStore) -> Encoded {
|
||||||
0,
|
0,
|
||||||
value,
|
value,
|
||||||
),
|
),
|
||||||
crate::op::Content::List(list) => match list {
|
crate::op::RemoteContent::List(list) => match list {
|
||||||
ListOp::Insert { slice, pos } => (
|
ListOp::Insert { slice, pos } => (
|
||||||
pos,
|
pos,
|
||||||
match &slice {
|
match &slice {
|
||||||
|
@ -155,7 +155,7 @@ fn encode_changes(store: &LogStore) -> Encoded {
|
||||||
(span.pos as usize, 0, LoroValue::I32(span.len as i32))
|
(span.pos as usize, 0, LoroValue::I32(span.len as i32))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
crate::op::Content::Dyn(_) => unreachable!(),
|
crate::op::RemoteContent::Dyn(_) => unreachable!(),
|
||||||
};
|
};
|
||||||
op_len += 1;
|
op_len += 1;
|
||||||
ops.push(OpEncoding {
|
ops.push(OpEncoding {
|
||||||
|
@ -256,7 +256,7 @@ fn decode_changes(
|
||||||
let content = match container_type {
|
let content = match container_type {
|
||||||
ContainerType::Map => {
|
ContainerType::Map => {
|
||||||
let key = keys[prop].clone();
|
let key = keys[prop].clone();
|
||||||
Content::Map(MapSet { key, value })
|
RemoteContent::Map(MapSet { key, value })
|
||||||
}
|
}
|
||||||
ContainerType::List | ContainerType::Text => {
|
ContainerType::List | ContainerType::Text => {
|
||||||
let pos = prop;
|
let pos = prop;
|
||||||
|
@ -278,7 +278,7 @@ fn decode_changes(
|
||||||
ListOp::Insert { slice, pos }
|
ListOp::Insert { slice, pos }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Content::List(list_op)
|
RemoteContent::List(list_op)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,14 @@ use smallvec::{smallvec, SmallVec};
|
||||||
pub struct Op {
|
pub struct Op {
|
||||||
pub(crate) counter: Counter,
|
pub(crate) counter: Counter,
|
||||||
pub(crate) container: ContainerIdx,
|
pub(crate) container: ContainerIdx,
|
||||||
pub(crate) content: Content,
|
pub(crate) content: RemoteContent,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RemoteOp {
|
pub struct RemoteOp {
|
||||||
pub(crate) counter: Counter,
|
pub(crate) counter: Counter,
|
||||||
pub(crate) container: ContainerID,
|
pub(crate) container: ContainerID,
|
||||||
pub(crate) contents: RleVec<[Content; 1]>,
|
pub(crate) contents: RleVec<[RemoteContent; 1]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RichOp includes lamport and timestamp info, which is used for conflict resolution.
|
/// RichOp includes lamport and timestamp info, which is used for conflict resolution.
|
||||||
|
@ -46,7 +46,7 @@ pub struct RichOp<'a> {
|
||||||
|
|
||||||
impl Op {
|
impl Op {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn new(id: ID, content: Content, container: u32) -> Self {
|
pub(crate) fn new(id: ID, content: RemoteContent, container: u32) -> Self {
|
||||||
Op {
|
Op {
|
||||||
counter: id.counter,
|
counter: id.counter,
|
||||||
content,
|
content,
|
||||||
|
@ -104,7 +104,7 @@ impl HasLength for Op {
|
||||||
impl Sliceable for Op {
|
impl Sliceable for Op {
|
||||||
fn slice(&self, from: usize, to: usize) -> Self {
|
fn slice(&self, from: usize, to: usize) -> Self {
|
||||||
assert!(to > from);
|
assert!(to > from);
|
||||||
let content: Content = self.content.slice(from, to);
|
let content: RemoteContent = self.content.slice(from, to);
|
||||||
Op {
|
Op {
|
||||||
counter: (self.counter + from as Counter),
|
counter: (self.counter + from as Counter),
|
||||||
content,
|
content,
|
||||||
|
|
|
@ -3,7 +3,10 @@ use std::any::{Any, TypeId};
|
||||||
use enum_as_inner::EnumAsInner;
|
use enum_as_inner::EnumAsInner;
|
||||||
use rle::{HasLength, Mergable, Sliceable};
|
use rle::{HasLength, Mergable, Sliceable};
|
||||||
|
|
||||||
use crate::container::{list::list_op::ListOp, map::MapSet};
|
use crate::container::{
|
||||||
|
list::list_op::{InnerListOp, ListOp},
|
||||||
|
map::{InnerMapSet, MapSet},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
|
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
|
||||||
pub enum ContentType {
|
pub enum ContentType {
|
||||||
|
@ -16,13 +19,20 @@ pub enum ContentType {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(EnumAsInner, Debug)]
|
#[derive(EnumAsInner, Debug)]
|
||||||
pub enum Content {
|
pub enum InnerContent {
|
||||||
|
Unknown(usize),
|
||||||
|
List(InnerListOp),
|
||||||
|
Map(InnerMapSet),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(EnumAsInner, Debug)]
|
||||||
|
pub enum RemoteContent {
|
||||||
Map(MapSet),
|
Map(MapSet),
|
||||||
List(ListOp),
|
List(ListOp),
|
||||||
Dyn(Box<dyn InsertContentTrait>),
|
Dyn(Box<dyn InsertContentTrait>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Content {
|
impl Clone for RemoteContent {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Map(arg0) => Self::Map(arg0.clone()),
|
Self::Map(arg0) => Self::Map(arg0.clone()),
|
||||||
|
@ -32,7 +42,7 @@ impl Clone for Content {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Content {
|
impl RemoteContent {
|
||||||
pub fn id(&self) -> ContentType {
|
pub fn id(&self) -> ContentType {
|
||||||
match self {
|
match self {
|
||||||
Self::Map(_) => ContentType::Map,
|
Self::Map(_) => ContentType::Map,
|
||||||
|
@ -90,35 +100,35 @@ impl<T: Mergable + Any> MergeableContent for T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasLength for Content {
|
impl HasLength for RemoteContent {
|
||||||
fn content_len(&self) -> usize {
|
fn content_len(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Content::Map(x) => x.content_len(),
|
RemoteContent::Map(x) => x.content_len(),
|
||||||
Content::Dyn(x) => x.content_len(),
|
RemoteContent::Dyn(x) => x.content_len(),
|
||||||
Content::List(x) => x.content_len(),
|
RemoteContent::List(x) => x.content_len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sliceable for Content {
|
impl Sliceable for RemoteContent {
|
||||||
fn slice(&self, from: usize, to: usize) -> Self {
|
fn slice(&self, from: usize, to: usize) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Content::Map(x) => Content::Map(x.slice(from, to)),
|
RemoteContent::Map(x) => RemoteContent::Map(x.slice(from, to)),
|
||||||
Content::Dyn(x) => Content::Dyn(x.slice_content(from, to)),
|
RemoteContent::Dyn(x) => RemoteContent::Dyn(x.slice_content(from, to)),
|
||||||
Content::List(x) => Content::List(x.slice(from, to)),
|
RemoteContent::List(x) => RemoteContent::List(x.slice(from, to)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mergable for Content {
|
impl Mergable for RemoteContent {
|
||||||
fn is_mergable(&self, other: &Self, _conf: &()) -> bool
|
fn is_mergable(&self, other: &Self, _conf: &()) -> bool
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Content::Map(x), Content::Map(y)) => x.is_mergable(y, &()),
|
(RemoteContent::Map(x), RemoteContent::Map(y)) => x.is_mergable(y, &()),
|
||||||
(Content::List(x), Content::List(y)) => x.is_mergable(y, &()),
|
(RemoteContent::List(x), RemoteContent::List(y)) => x.is_mergable(y, &()),
|
||||||
(Content::Dyn(x), Content::Dyn(y)) => x.is_mergable_content(&**y),
|
(RemoteContent::Dyn(x), RemoteContent::Dyn(y)) => x.is_mergable_content(&**y),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,15 +138,15 @@ impl Mergable for Content {
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Content::Map(x) => match _other {
|
RemoteContent::Map(x) => match _other {
|
||||||
Content::Map(y) => x.merge(y, &()),
|
RemoteContent::Map(y) => x.merge(y, &()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
Content::List(x) => match _other {
|
RemoteContent::List(x) => match _other {
|
||||||
Content::List(y) => x.merge(y, &()),
|
RemoteContent::List(y) => x.merge(y, &()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
Content::Dyn(x) => x.merge_content(&**_other.as_dyn().unwrap()),
|
RemoteContent::Dyn(x) => x.merge_content(&**_other.as_dyn().unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ fn size_of() {
|
||||||
use crate::{
|
use crate::{
|
||||||
container::{map::MapSet, text::text_content::ListSlice, ContainerID},
|
container::{map::MapSet, text::text_content::ListSlice, ContainerID},
|
||||||
id::ID,
|
id::ID,
|
||||||
op::{Content, Op},
|
op::{Op, RemoteContent},
|
||||||
span::IdSpan,
|
span::IdSpan,
|
||||||
Container, InternalString,
|
Container, InternalString,
|
||||||
};
|
};
|
||||||
|
@ -28,7 +28,7 @@ fn size_of() {
|
||||||
|
|
||||||
println!("Change {}", std::mem::size_of::<Change>());
|
println!("Change {}", std::mem::size_of::<Change>());
|
||||||
println!("Op {}", std::mem::size_of::<Op>());
|
println!("Op {}", std::mem::size_of::<Op>());
|
||||||
println!("InsertContent {}", std::mem::size_of::<Content>());
|
println!("InsertContent {}", std::mem::size_of::<RemoteContent>());
|
||||||
println!("MapSet {}", std::mem::size_of::<MapSet>());
|
println!("MapSet {}", std::mem::size_of::<MapSet>());
|
||||||
println!("ListSlice {}", std::mem::size_of::<ListSlice>());
|
println!("ListSlice {}", std::mem::size_of::<ListSlice>());
|
||||||
println!("Box {}", std::mem::size_of::<Box<dyn Container>>());
|
println!("Box {}", std::mem::size_of::<Box<dyn Container>>());
|
||||||
|
|
Loading…
Reference in a new issue