mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-22 12:57:20 +00:00
feat: export diff batch to ffi
This commit is contained in:
parent
07500dab34
commit
db2353192a
5 changed files with 300 additions and 41 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -34,6 +34,7 @@
|
||||||
"pointee",
|
"pointee",
|
||||||
"reparent",
|
"reparent",
|
||||||
"RUSTFLAGS",
|
"RUSTFLAGS",
|
||||||
|
"serde",
|
||||||
"smstring",
|
"smstring",
|
||||||
"sstable",
|
"sstable",
|
||||||
"Stewen",
|
"Stewen",
|
||||||
|
|
|
@ -13,10 +13,10 @@ use loro::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
event::{DiffEvent, Subscriber},
|
event::{DiffBatch, DiffEvent, Subscriber},
|
||||||
AbsolutePosition, Configure, ContainerID, ContainerIdLike, Cursor, Frontiers, Index,
|
AbsolutePosition, Configure, ContainerID, ContainerIdLike, Cursor, Frontiers, Index,
|
||||||
LoroCounter, LoroList, LoroMap, LoroMovableList, LoroText, LoroTree, LoroValue, StyleConfigMap,
|
LoroCounter, LoroList, LoroMap, LoroMovableList, LoroText, LoroTree, LoroValue, StyleConfigMap,
|
||||||
ValueOrContainer, VersionVector,
|
ValueOrContainer, VersionVector, VersionVectorDiff,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Decodes the metadata for an imported blob from the provided bytes.
|
/// Decodes the metadata for an imported blob from the provided bytes.
|
||||||
|
@ -88,10 +88,13 @@ impl LoroDoc {
|
||||||
self.doc.set_record_timestamp(record);
|
self.doc.set_record_timestamp(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the interval of mergeable changes, in milliseconds.
|
/// Set the interval of mergeable changes, **in seconds**.
|
||||||
///
|
///
|
||||||
/// If two continuous local changes are within the interval, they will be merged into one change.
|
/// If two continuous local changes are within the interval, they will be merged into one change.
|
||||||
/// The default value is 1000 seconds.
|
/// The default value is 1000 seconds.
|
||||||
|
///
|
||||||
|
/// By default, we record timestamps in seconds for each change. So if the merge interval is 1, and changes A and B
|
||||||
|
/// have timestamps of 3 and 4 respectively, then they will be merged into one change
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_change_merge_interval(&self, interval: i64) {
|
pub fn set_change_merge_interval(&self, interval: i64) {
|
||||||
self.doc.set_change_merge_interval(interval);
|
self.doc.set_change_merge_interval(interval);
|
||||||
|
@ -249,6 +252,8 @@ impl LoroDoc {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set commit message for the current uncommitted changes
|
/// Set commit message for the current uncommitted changes
|
||||||
|
///
|
||||||
|
/// It will be persisted.
|
||||||
pub fn set_next_commit_message(&self, msg: &str) {
|
pub fn set_next_commit_message(&self, msg: &str) {
|
||||||
self.doc.set_next_commit_message(msg)
|
self.doc.set_next_commit_message(msg)
|
||||||
}
|
}
|
||||||
|
@ -291,6 +296,32 @@ impl LoroDoc {
|
||||||
serde_json::to_string(&json).unwrap()
|
serde_json::to_string(&json).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Export the current state with json-string format of the document, without peer compression.
|
||||||
|
///
|
||||||
|
/// Compared to [`export_json_updates`], this method does not compress the peer IDs in the updates.
|
||||||
|
/// So the operations are easier to be processed by application code.
|
||||||
|
#[inline]
|
||||||
|
pub fn export_json_updates_without_peer_compression(
|
||||||
|
&self,
|
||||||
|
start_vv: &VersionVector,
|
||||||
|
end_vv: &VersionVector,
|
||||||
|
) -> String {
|
||||||
|
let json = self
|
||||||
|
.doc
|
||||||
|
.export_json_updates_without_peer_compression(&start_vv.into(), &end_vv.into());
|
||||||
|
serde_json::to_string(&json).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Export the readable [`Change`]s in the given [`IdSpan`]
|
||||||
|
// TODO: swift type
|
||||||
|
pub fn export_json_in_id_span(&self, id_span: IdSpan) -> Vec<String> {
|
||||||
|
self.doc
|
||||||
|
.export_json_in_id_span(id_span)
|
||||||
|
.into_iter()
|
||||||
|
.map(|x| serde_json::to_string(&x).unwrap())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: add export method
|
// TODO: add export method
|
||||||
/// Export all the ops not included in the given `VersionVector`
|
/// Export all the ops not included in the given `VersionVector`
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -464,6 +495,58 @@ impl LoroDoc {
|
||||||
.map(|x| Arc::new(x) as Arc<dyn ValueOrContainer>)
|
.map(|x| Arc::new(x) as Arc<dyn ValueOrContainer>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// The path can be specified in different ways depending on the container type:
|
||||||
|
///
|
||||||
|
/// For Tree:
|
||||||
|
/// 1. Using node IDs: `tree/{node_id}/property`
|
||||||
|
/// 2. Using indices: `tree/0/1/property`
|
||||||
|
///
|
||||||
|
/// For List and MovableList:
|
||||||
|
/// - Using indices: `list/0` or `list/1/property`
|
||||||
|
///
|
||||||
|
/// For Map:
|
||||||
|
/// - Using keys: `map/key` or `map/nested/property`
|
||||||
|
///
|
||||||
|
/// For tree structures, index-based paths follow depth-first traversal order.
|
||||||
|
/// The indices start from 0 and represent the position of a node among its siblings.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// # use loro::{LoroDoc, LoroValue};
|
||||||
|
/// let doc = LoroDoc::new();
|
||||||
|
///
|
||||||
|
/// // Tree example
|
||||||
|
/// let tree = doc.get_tree("tree");
|
||||||
|
/// let root = tree.create(None).unwrap();
|
||||||
|
/// tree.get_meta(root).unwrap().insert("name", "root").unwrap();
|
||||||
|
/// // Access tree by ID or index
|
||||||
|
/// let name1 = doc.get_by_str_path(&format!("tree/{}/name", root)).unwrap().into_value().unwrap();
|
||||||
|
/// let name2 = doc.get_by_str_path("tree/0/name").unwrap().into_value().unwrap();
|
||||||
|
/// assert_eq!(name1, name2);
|
||||||
|
///
|
||||||
|
/// // List example
|
||||||
|
/// let list = doc.get_list("list");
|
||||||
|
/// list.insert(0, "first").unwrap();
|
||||||
|
/// list.insert(1, "second").unwrap();
|
||||||
|
/// // Access list by index
|
||||||
|
/// let item = doc.get_by_str_path("list/0");
|
||||||
|
/// assert_eq!(item.unwrap().into_value().unwrap().into_string().unwrap(), "first".into());
|
||||||
|
///
|
||||||
|
/// // Map example
|
||||||
|
/// let map = doc.get_map("map");
|
||||||
|
/// map.insert("key", "value").unwrap();
|
||||||
|
/// // Access map by key
|
||||||
|
/// let value = doc.get_by_str_path("map/key");
|
||||||
|
/// assert_eq!(value.unwrap().into_value().unwrap().into_string().unwrap(), "value".into());
|
||||||
|
///
|
||||||
|
/// // MovableList example
|
||||||
|
/// let mlist = doc.get_movable_list("mlist");
|
||||||
|
/// mlist.insert(0, "item").unwrap();
|
||||||
|
/// // Access movable list by index
|
||||||
|
/// let item = doc.get_by_str_path("mlist/0");
|
||||||
|
/// assert_eq!(item.unwrap().into_value().unwrap().into_string().unwrap(), "item".into());
|
||||||
|
/// ```
|
||||||
pub fn get_by_str_path(&self, path: &str) -> Option<Arc<dyn ValueOrContainer>> {
|
pub fn get_by_str_path(&self, path: &str) -> Option<Arc<dyn ValueOrContainer>> {
|
||||||
self.doc
|
self.doc
|
||||||
.get_by_str_path(path)
|
.get_by_str_path(path)
|
||||||
|
@ -616,6 +699,38 @@ impl LoroDoc {
|
||||||
pub fn get_pending_txn_len(&self) -> u32 {
|
pub fn get_pending_txn_len(&self) -> u32 {
|
||||||
self.doc.get_pending_txn_len() as u32
|
self.doc.get_pending_txn_len() as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the operation id spans that between the `from` version and the `to` version.
|
||||||
|
#[inline]
|
||||||
|
pub fn find_id_spans_between(&self, from: &Frontiers, to: &Frontiers) -> VersionVectorDiff {
|
||||||
|
self.doc
|
||||||
|
.find_id_spans_between(&from.into(), &to.into())
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Revert the current document state back to the target version
|
||||||
|
///
|
||||||
|
/// Internally, it will generate a series of local operations that can revert the
|
||||||
|
/// current doc to the target version. It will calculate the diff between the current
|
||||||
|
/// state and the target state, and apply the diff to the current state.
|
||||||
|
#[inline]
|
||||||
|
pub fn revert_to(&self, version: &Frontiers) -> LoroResult<()> {
|
||||||
|
self.doc.revert_to(&version.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply a diff to the current document state.
|
||||||
|
///
|
||||||
|
/// Internally, it will apply the diff to the current state.
|
||||||
|
#[inline]
|
||||||
|
pub fn apply_diff(&self, diff: DiffBatch) -> LoroResult<()> {
|
||||||
|
self.doc.apply_diff(diff.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculate the diff between two versions
|
||||||
|
#[inline]
|
||||||
|
pub fn diff(&self, a: &Frontiers, b: &Frontiers) -> LoroResult<DiffBatch> {
|
||||||
|
self.doc.diff(&a.into(), &b.into()).map(|x| x.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ChangeAncestorsTraveler: Sync + Send {
|
pub trait ChangeAncestorsTraveler: Sync + Send {
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
use loro::{EventTriggerKind, TreeID};
|
use loro::{EventTriggerKind, FractionalIndex, TreeID};
|
||||||
|
|
||||||
use crate::{ContainerID, LoroValue, TreeParentId, ValueOrContainer};
|
use crate::{
|
||||||
|
convert_trait_to_v_or_container, ContainerID, LoroValue, TreeParentId, ValueOrContainer,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait Subscriber: Sync + Send {
|
pub trait Subscriber: Sync + Send {
|
||||||
fn on_diff(&self, diff: DiffEvent);
|
fn on_diff(&self, diff: DiffEvent);
|
||||||
|
@ -135,6 +141,76 @@ impl From<loro::TextDelta> for TextDelta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ListDiffItem> for loro::event::ListDiffItem {
|
||||||
|
fn from(value: ListDiffItem) -> Self {
|
||||||
|
match value {
|
||||||
|
ListDiffItem::Insert { insert, is_move } => loro::event::ListDiffItem::Insert {
|
||||||
|
insert: insert
|
||||||
|
.into_iter()
|
||||||
|
.map(convert_trait_to_v_or_container)
|
||||||
|
.collect(),
|
||||||
|
is_move,
|
||||||
|
},
|
||||||
|
ListDiffItem::Delete { delete } => loro::event::ListDiffItem::Delete {
|
||||||
|
delete: delete as usize,
|
||||||
|
},
|
||||||
|
ListDiffItem::Retain { retain } => loro::event::ListDiffItem::Retain {
|
||||||
|
retain: retain as usize,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MapDelta> for loro::event::MapDelta<'static> {
|
||||||
|
fn from(value: MapDelta) -> Self {
|
||||||
|
loro::event::MapDelta {
|
||||||
|
updated: value
|
||||||
|
.updated
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (Cow::Owned(k), v.map(convert_trait_to_v_or_container)))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TreeDiffItem> for loro::TreeDiffItem {
|
||||||
|
fn from(value: TreeDiffItem) -> Self {
|
||||||
|
let target: TreeID = value.target;
|
||||||
|
let action = match value.action {
|
||||||
|
TreeExternalDiff::Create {
|
||||||
|
parent,
|
||||||
|
index,
|
||||||
|
fractional_index,
|
||||||
|
} => loro::TreeExternalDiff::Create {
|
||||||
|
parent: parent.into(),
|
||||||
|
index: index as usize,
|
||||||
|
position: FractionalIndex::from_hex_string(fractional_index),
|
||||||
|
},
|
||||||
|
TreeExternalDiff::Move {
|
||||||
|
parent,
|
||||||
|
index,
|
||||||
|
fractional_index,
|
||||||
|
old_parent,
|
||||||
|
old_index,
|
||||||
|
} => loro::TreeExternalDiff::Move {
|
||||||
|
parent: parent.into(),
|
||||||
|
index: index as usize,
|
||||||
|
position: FractionalIndex::from_hex_string(fractional_index),
|
||||||
|
old_parent: old_parent.into(),
|
||||||
|
old_index: old_index as usize,
|
||||||
|
},
|
||||||
|
TreeExternalDiff::Delete {
|
||||||
|
old_parent,
|
||||||
|
old_index,
|
||||||
|
} => loro::TreeExternalDiff::Delete {
|
||||||
|
old_parent: old_parent.into(),
|
||||||
|
old_index: old_index as usize,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
loro::TreeDiffItem { target, action }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum ListDiffItem {
|
pub enum ListDiffItem {
|
||||||
/// Insert a new element into the list.
|
/// Insert a new element into the list.
|
||||||
Insert {
|
Insert {
|
||||||
|
@ -263,40 +339,9 @@ impl From<&loro::event::Diff<'_>> for Diff {
|
||||||
}
|
}
|
||||||
Diff::List { diff: ans }
|
Diff::List { diff: ans }
|
||||||
}
|
}
|
||||||
loro::event::Diff::Text(t) => {
|
loro::event::Diff::Text(t) => Diff::Text {
|
||||||
let mut ans = Vec::new();
|
diff: t.iter().map(|i| i.clone().into()).collect(),
|
||||||
for item in t.iter() {
|
},
|
||||||
match item {
|
|
||||||
loro::TextDelta::Retain { retain, attributes } => {
|
|
||||||
ans.push(TextDelta::Retain {
|
|
||||||
retain: *retain as u32,
|
|
||||||
attributes: attributes.as_ref().map(|a| {
|
|
||||||
a.iter()
|
|
||||||
.map(|(k, v)| (k.to_string(), v.clone().into()))
|
|
||||||
.collect()
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
loro::TextDelta::Insert { insert, attributes } => {
|
|
||||||
ans.push(TextDelta::Insert {
|
|
||||||
insert: insert.to_string(),
|
|
||||||
attributes: attributes.as_ref().map(|a| {
|
|
||||||
a.iter()
|
|
||||||
.map(|(k, v)| (k.to_string(), v.clone().into()))
|
|
||||||
.collect()
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
loro::TextDelta::Delete { delete } => {
|
|
||||||
ans.push(TextDelta::Delete {
|
|
||||||
delete: *delete as u32,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Diff::Text { diff: ans }
|
|
||||||
}
|
|
||||||
loro::event::Diff::Map(m) => {
|
loro::event::Diff::Map(m) => {
|
||||||
let mut updated = HashMap::new();
|
let mut updated = HashMap::new();
|
||||||
for (key, value) in m.updated.iter() {
|
for (key, value) in m.updated.iter() {
|
||||||
|
@ -359,3 +404,60 @@ impl From<&loro::event::Diff<'_>> for Diff {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Diff> for loro::event::Diff<'static> {
|
||||||
|
fn from(value: Diff) -> Self {
|
||||||
|
match value {
|
||||||
|
Diff::List { diff } => {
|
||||||
|
loro::event::Diff::List(diff.into_iter().map(|i| i.into()).collect())
|
||||||
|
}
|
||||||
|
Diff::Text { diff } => {
|
||||||
|
loro::event::Diff::Text(diff.into_iter().map(|i| i.into()).collect())
|
||||||
|
}
|
||||||
|
Diff::Map { diff } => loro::event::Diff::Map(diff.into()),
|
||||||
|
Diff::Tree { diff } => loro::event::Diff::Tree(Cow::Owned(loro::TreeDiff {
|
||||||
|
diff: diff.diff.into_iter().map(|i| i.into()).collect(),
|
||||||
|
})),
|
||||||
|
Diff::Counter { diff } => loro::event::Diff::Counter(diff),
|
||||||
|
Diff::Unknown => loro::event::Diff::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct DiffBatch(Mutex<loro::event::DiffBatch>);
|
||||||
|
|
||||||
|
impl DiffBatch {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(Default::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&self, cid: ContainerID, diff: Diff) -> Option<Diff> {
|
||||||
|
let mut batch = self.0.lock().unwrap();
|
||||||
|
if let Err(diff) = batch.push(cid.into(), diff.into()) {
|
||||||
|
Some((&diff).into())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn diffs(&self) -> Vec<(ContainerID, Diff)> {
|
||||||
|
let batch = self.0.lock().unwrap();
|
||||||
|
batch
|
||||||
|
.iter()
|
||||||
|
.map(|(id, diff)| (id.into(), diff.into()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DiffBatch> for loro::event::DiffBatch {
|
||||||
|
fn from(value: DiffBatch) -> Self {
|
||||||
|
value.0.into_inner().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<loro::event::DiffBatch> for DiffBatch {
|
||||||
|
fn from(value: loro::event::DiffBatch) -> Self {
|
||||||
|
Self(Mutex::new(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ pub trait ValueOrContainer: Send + Sync {
|
||||||
fn is_value(&self) -> bool;
|
fn is_value(&self) -> bool;
|
||||||
fn is_container(&self) -> bool;
|
fn is_container(&self) -> bool;
|
||||||
fn as_value(&self) -> Option<LoroValue>;
|
fn as_value(&self) -> Option<LoroValue>;
|
||||||
|
fn container_type(&self) -> Option<ContainerType>;
|
||||||
fn as_container(&self) -> Option<ContainerID>;
|
fn as_container(&self) -> Option<ContainerID>;
|
||||||
fn as_loro_list(&self) -> Option<Arc<LoroList>>;
|
fn as_loro_list(&self) -> Option<Arc<LoroList>>;
|
||||||
fn as_loro_text(&self) -> Option<Arc<LoroText>>;
|
fn as_loro_text(&self) -> Option<Arc<LoroText>>;
|
||||||
|
@ -48,6 +49,7 @@ pub trait ValueOrContainer: Send + Sync {
|
||||||
fn as_loro_movable_list(&self) -> Option<Arc<LoroMovableList>>;
|
fn as_loro_movable_list(&self) -> Option<Arc<LoroMovableList>>;
|
||||||
fn as_loro_tree(&self) -> Option<Arc<LoroTree>>;
|
fn as_loro_tree(&self) -> Option<Arc<LoroTree>>;
|
||||||
fn as_loro_counter(&self) -> Option<Arc<LoroCounter>>;
|
fn as_loro_counter(&self) -> Option<Arc<LoroCounter>>;
|
||||||
|
fn as_unknown(&self) -> Option<Arc<LoroUnknown>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValueOrContainer for loro::ValueOrContainer {
|
impl ValueOrContainer for loro::ValueOrContainer {
|
||||||
|
@ -59,12 +61,17 @@ impl ValueOrContainer for loro::ValueOrContainer {
|
||||||
loro::ValueOrContainer::is_container(self)
|
loro::ValueOrContainer::is_container(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn container_type(&self) -> Option<ContainerType> {
|
||||||
|
loro::ValueOrContainer::as_container(self).map(|c| c.id().container_type().into())
|
||||||
|
}
|
||||||
|
|
||||||
fn as_value(&self) -> Option<LoroValue> {
|
fn as_value(&self) -> Option<LoroValue> {
|
||||||
loro::ValueOrContainer::as_value(self)
|
loro::ValueOrContainer::as_value(self)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(LoroValue::from)
|
.map(LoroValue::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: pass Container to Swift
|
||||||
fn as_container(&self) -> Option<ContainerID> {
|
fn as_container(&self) -> Option<ContainerID> {
|
||||||
loro::ValueOrContainer::as_container(self).map(|c| c.id().into())
|
loro::ValueOrContainer::as_container(self).map(|c| c.id().into())
|
||||||
}
|
}
|
||||||
|
@ -122,4 +129,37 @@ impl ValueOrContainer for loro::ValueOrContainer {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_unknown(&self) -> Option<Arc<LoroUnknown>> {
|
||||||
|
match self {
|
||||||
|
loro::ValueOrContainer::Container(Container::Unknown(c)) => {
|
||||||
|
Some(Arc::new(LoroUnknown { unknown: c.clone() }))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_trait_to_v_or_container<T: AsRef<dyn ValueOrContainer>>(i: T) -> loro::ValueOrContainer {
|
||||||
|
let v = i.as_ref();
|
||||||
|
if v.is_value() {
|
||||||
|
loro::ValueOrContainer::Value(v.as_value().unwrap().into())
|
||||||
|
} else {
|
||||||
|
let container = match v.container_type().unwrap() {
|
||||||
|
ContainerType::List => Container::List((*v.as_loro_list().unwrap()).clone().list),
|
||||||
|
ContainerType::Text => Container::Text((*v.as_loro_text().unwrap()).clone().text),
|
||||||
|
ContainerType::Map => Container::Map((*v.as_loro_map().unwrap()).clone().map),
|
||||||
|
ContainerType::MovableList => {
|
||||||
|
Container::MovableList((*v.as_loro_movable_list().unwrap()).clone().list)
|
||||||
|
}
|
||||||
|
ContainerType::Tree => Container::Tree((*v.as_loro_tree().unwrap()).clone().tree),
|
||||||
|
ContainerType::Counter => {
|
||||||
|
Container::Counter((*v.as_loro_counter().unwrap()).clone().counter)
|
||||||
|
}
|
||||||
|
ContainerType::Unknown { kind: _ } => {
|
||||||
|
Container::Unknown((*v.as_unknown().unwrap()).clone().unknown)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loro::ValueOrContainer::Container(container)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ use delta::DeltaRope;
|
||||||
use enum_as_inner::EnumAsInner;
|
use enum_as_inner::EnumAsInner;
|
||||||
use loro_common::IdLp;
|
use loro_common::IdLp;
|
||||||
use loro_internal::container::ContainerID;
|
use loro_internal::container::ContainerID;
|
||||||
use loro_internal::delta::{ResolvedMapDelta, ResolvedMapValue, TreeDiff};
|
pub use loro_internal::delta::TreeDiff;
|
||||||
|
use loro_internal::delta::{ResolvedMapDelta, ResolvedMapValue};
|
||||||
use loro_internal::event::{EventTriggerKind, ListDeltaMeta};
|
use loro_internal::event::{EventTriggerKind, ListDeltaMeta};
|
||||||
use loro_internal::handler::{TextDelta, ValueOrHandler};
|
use loro_internal::handler::{TextDelta, ValueOrHandler};
|
||||||
use loro_internal::undo::DiffBatch as InnerDiffBatch;
|
use loro_internal::undo::DiffBatch as InnerDiffBatch;
|
||||||
|
|
Loading…
Reference in a new issue