mirror of
https://github.com/loro-dev/loro.git
synced 2025-02-02 11:06:14 +00:00
refactor: add linear diff calc mode to tree
This commit is contained in:
parent
9d8221ca29
commit
de78cf9636
1 changed files with 83 additions and 13 deletions
|
@ -20,20 +20,80 @@ use super::{DiffCalculatorTrait, DiffMode};
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct TreeDiffCalculator {
|
pub(crate) struct TreeDiffCalculator {
|
||||||
container: ContainerIdx,
|
container: ContainerIdx,
|
||||||
|
mode: TreeDiffCalculatorMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum TreeDiffCalculatorMode {
|
||||||
|
UndoRedo,
|
||||||
|
Linear(TreeDelta),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiffCalculatorTrait for TreeDiffCalculator {
|
impl DiffCalculatorTrait for TreeDiffCalculator {
|
||||||
fn start_tracking(&mut self, _oplog: &OpLog, _vv: &crate::VersionVector, mode: DiffMode) {}
|
fn start_tracking(&mut self, _oplog: &OpLog, _vv: &crate::VersionVector, mode: DiffMode) {
|
||||||
|
if mode == DiffMode::Linear {
|
||||||
|
self.mode = TreeDiffCalculatorMode::Linear(TreeDelta::default());
|
||||||
|
} else {
|
||||||
|
self.mode = TreeDiffCalculatorMode::UndoRedo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn apply_change(
|
fn apply_change(
|
||||||
&mut self,
|
&mut self,
|
||||||
_oplog: &OpLog,
|
_oplog: &OpLog,
|
||||||
_op: crate::op::RichOp,
|
op: crate::op::RichOp,
|
||||||
_vv: Option<&crate::VersionVector>,
|
_vv: Option<&crate::VersionVector>,
|
||||||
) {
|
) {
|
||||||
|
match self.mode {
|
||||||
|
TreeDiffCalculatorMode::UndoRedo => {}
|
||||||
|
TreeDiffCalculatorMode::Linear(ref mut delta) => {
|
||||||
|
let id_full = op.id_full();
|
||||||
|
let op = op.op();
|
||||||
|
let content = op.content.as_tree().unwrap();
|
||||||
|
|
||||||
|
let item: TreeDeltaItem = match content {
|
||||||
|
crate::container::tree::tree_op::TreeOp::Create {
|
||||||
|
target,
|
||||||
|
parent,
|
||||||
|
position,
|
||||||
|
} => TreeDeltaItem {
|
||||||
|
target: *target,
|
||||||
|
action: TreeInternalDiff::Create {
|
||||||
|
parent: (*parent).into(),
|
||||||
|
position: position.clone(),
|
||||||
|
},
|
||||||
|
last_effective_move_op_id: id_full,
|
||||||
|
},
|
||||||
|
crate::container::tree::tree_op::TreeOp::Move {
|
||||||
|
target,
|
||||||
|
parent,
|
||||||
|
position,
|
||||||
|
} => TreeDeltaItem {
|
||||||
|
target: *target,
|
||||||
|
action: TreeInternalDiff::Move {
|
||||||
|
parent: (*parent).into(),
|
||||||
|
position: position.clone(),
|
||||||
|
},
|
||||||
|
last_effective_move_op_id: id_full,
|
||||||
|
},
|
||||||
|
crate::container::tree::tree_op::TreeOp::Delete { target } => TreeDeltaItem {
|
||||||
|
target: *target,
|
||||||
|
action: TreeInternalDiff::Delete {
|
||||||
|
parent: TreeParentId::Deleted,
|
||||||
|
position: None,
|
||||||
|
},
|
||||||
|
last_effective_move_op_id: id_full,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
delta.diff.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_this_round(&mut self) {}
|
fn finish_this_round(&mut self) {
|
||||||
|
self.mode = TreeDiffCalculatorMode::UndoRedo;
|
||||||
|
}
|
||||||
|
|
||||||
fn calculate_diff(
|
fn calculate_diff(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -42,22 +102,32 @@ impl DiffCalculatorTrait for TreeDiffCalculator {
|
||||||
to: &crate::VersionVector,
|
to: &crate::VersionVector,
|
||||||
mut on_new_container: impl FnMut(&ContainerID),
|
mut on_new_container: impl FnMut(&ContainerID),
|
||||||
) -> (InternalDiff, DiffMode) {
|
) -> (InternalDiff, DiffMode) {
|
||||||
let diff = self.diff(oplog, from, to);
|
match &mut self.mode {
|
||||||
diff.diff.iter().for_each(|d| {
|
TreeDiffCalculatorMode::UndoRedo => {
|
||||||
// the metadata could be modified before, so (re)create a node need emit the map container diffs
|
let diff = self.diff(oplog, from, to);
|
||||||
// `Create` here is because maybe in a diff calc uncreate and then create back
|
diff.diff.iter().for_each(|d| {
|
||||||
if matches!(d.action, TreeInternalDiff::Create { .. }) {
|
// the metadata could be modified before, so (re)create a node need emit the map container diffs
|
||||||
on_new_container(&d.target.associated_meta_container())
|
// `Create` here is because maybe in a diff calc uncreate and then create back
|
||||||
}
|
if matches!(d.action, TreeInternalDiff::Create { .. }) {
|
||||||
});
|
on_new_container(&d.target.associated_meta_container())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
(InternalDiff::Tree(diff), DiffMode::Checkout)
|
(InternalDiff::Tree(diff), DiffMode::Checkout)
|
||||||
|
}
|
||||||
|
TreeDiffCalculatorMode::Linear(ans) => {
|
||||||
|
(InternalDiff::Tree(std::mem::take(ans)), DiffMode::Linear)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeDiffCalculator {
|
impl TreeDiffCalculator {
|
||||||
pub(crate) fn new(container: ContainerIdx) -> Self {
|
pub(crate) fn new(container: ContainerIdx) -> Self {
|
||||||
Self { container }
|
Self {
|
||||||
|
container,
|
||||||
|
mode: TreeDiffCalculatorMode::UndoRedo,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diff(&mut self, oplog: &OpLog, from: &VersionVector, to: &VersionVector) -> TreeDelta {
|
fn diff(&mut self, oplog: &OpLog, from: &VersionVector, to: &VersionVector) -> TreeDelta {
|
||||||
|
|
Loading…
Reference in a new issue