loro/crates/loro-internal/src/event.rs

159 lines
4.4 KiB
Rust
Raw Normal View History

use enum_as_inner::EnumAsInner;
2022-11-29 10:31:57 +00:00
use serde::{Deserialize, Serialize};
2023-03-10 02:50:05 +00:00
use smallvec::SmallVec;
2022-11-23 08:26:38 +00:00
2023-03-01 13:37:58 +00:00
use crate::{
delta::{Delta, MapDelta, MapDiff},
2023-07-10 04:06:11 +00:00
text::text_content::SliceRanges,
2023-03-05 09:38:26 +00:00
InternalString, LoroValue,
2023-03-01 13:37:58 +00:00
};
2022-11-23 17:01:40 +00:00
use std::borrow::Cow;
use loro_common::ContainerID;
use crate::{container::idx::ContainerIdx, version::Frontiers};
#[derive(Debug, Clone)]
pub struct ContainerDiff {
pub id: ContainerID,
pub path: Vec<(ContainerID, Index)>,
pub(crate) idx: ContainerIdx,
pub diff: Diff,
}
#[derive(Debug, Clone)]
pub struct DiffEvent<'a> {
/// whether the event comes from the children of the container.
pub from_children: bool,
pub container: &'a ContainerDiff,
pub doc: &'a DocDiff,
2022-11-23 08:26:38 +00:00
}
/// It's the exposed event type.
/// It's exposed to the user. The user can use this to apply the diff to their local state.
///
/// [DocDiff] may include the diff that calculated from several transactions and imports.
/// They all should have the same origin and local flag.
#[derive(Debug, Clone)]
pub struct DocDiff {
pub from: Frontiers,
pub to: Frontiers,
pub origin: InternalString,
pub local: bool,
pub diff: Vec<ContainerDiff>,
2022-11-23 08:26:38 +00:00
}
#[derive(Debug, Clone)]
pub(crate) struct InternalContainerDiff {
pub(crate) idx: ContainerIdx,
pub(crate) diff: Diff,
2022-12-30 09:50:23 +00:00
}
/// It's used for transmitting and recording the diff internally.
///
/// It can be convert into a [DocDiff].
// Internally, we need to batch the diff then calculate the event. Because
// we need to sort the diff by containers' created time, to make sure the
// the path to each container is up-to-date.
#[derive(Debug, Clone)]
pub(crate) struct InternalDocDiff<'a> {
pub(crate) origin: InternalString,
pub(crate) local: bool,
pub(crate) diff: Cow<'a, [InternalContainerDiff]>,
pub(crate) new_version: Cow<'a, Frontiers>,
}
impl<'a> InternalDocDiff<'a> {
pub fn into_owned(self) -> InternalDocDiff<'static> {
InternalDocDiff {
origin: self.origin,
local: self.local,
diff: Cow::Owned((*self.diff).to_owned()),
new_version: Cow::Owned((*self.new_version).to_owned()),
}
}
pub fn can_merge(&self, other: &Self) -> bool {
self.origin == other.origin && self.local == other.local
}
}
#[cfg(test)]
mod test {
use std::sync::Arc;
use crate::LoroDoc;
#[test]
fn test_text_event() {
let loro = LoroDoc::new();
loro.subscribe_deep(Arc::new(|event| {
assert_eq!(
&event.container.diff.as_text().unwrap().vec[0]
.as_insert()
.unwrap()
.0,
&"h223ello"
);
dbg!(event);
}));
let mut txn = loro.txn().unwrap();
let text = loro.get_text("id");
text.insert(&mut txn, 0, "hello").unwrap();
text.insert(&mut txn, 1, "223").unwrap();
txn.commit().unwrap();
}
2022-12-30 09:50:23 +00:00
}
pub type Path = SmallVec<[Index; 4]>;
2022-11-23 08:26:38 +00:00
2022-11-29 10:31:57 +00:00
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
2022-11-23 08:26:38 +00:00
pub enum Index {
Key(InternalString),
2022-11-23 10:12:23 +00:00
Seq(usize),
2022-11-23 08:26:38 +00:00
}
2023-07-28 05:38:52 +00:00
/// Diff is the diff between two versions of a container.
/// It's used to describe the change of a container and the events.
///
/// # Internal
///
/// SeqRaw & SeqRawUtf16 is internal stuff, it should not be exposed to user.
/// The len inside SeqRaw uses utf8 for Text by default.
///
/// Text always uses platform specific indexes:
///
/// - When `wasm` is enabled, it should use utf16 indexes.
/// - When `wasm` is disabled, it should use utf8 indexes.
2023-01-11 13:40:16 +00:00
#[derive(Clone, Debug, EnumAsInner, Serialize)]
2022-11-23 08:26:38 +00:00
pub enum Diff {
2023-03-05 09:38:26 +00:00
List(Delta<Vec<LoroValue>>),
2023-07-07 13:54:47 +00:00
SeqRaw(Delta<SliceRanges>),
2023-07-28 05:38:52 +00:00
SeqRawUtf16(Delta<SliceRanges>),
Text(Delta<String>),
2023-07-07 11:12:41 +00:00
/// @deprecated
2023-03-10 02:50:05 +00:00
Map(MapDiff<LoroValue>),
2023-07-04 06:31:50 +00:00
NewMap(MapDelta),
2022-11-23 08:26:38 +00:00
}
2023-07-22 11:02:22 +00:00
impl Diff {
pub(crate) fn compose(self, diff: Diff) -> Result<Diff, Self> {
// PERF: avoid clone
match (self, diff) {
(Diff::List(a), Diff::List(b)) => Ok(Diff::List(a.compose(b))),
(Diff::SeqRaw(a), Diff::SeqRaw(b)) => Ok(Diff::SeqRaw(a.compose(b))),
(Diff::Text(a), Diff::Text(b)) => Ok(Diff::Text(a.compose(b))),
(Diff::Map(a), Diff::Map(b)) => Ok(Diff::Map(a.compose(b))),
(Diff::NewMap(a), Diff::NewMap(b)) => Ok(Diff::NewMap(a.compose(b))),
(a, _) => Err(a),
}
}
}
impl Default for Diff {
fn default() -> Self {
Diff::List(Delta::default())
}
}