mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: update lib-ot documentation again and rename some structs
This commit is contained in:
parent
a47af561ab
commit
00d81a329f
@ -13,7 +13,7 @@ use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision
|
|||||||
use flowy_revision::disk::{RevisionRecord, RevisionState};
|
use flowy_revision::disk::{RevisionRecord, RevisionState};
|
||||||
use flowy_revision::mk_text_block_revision_disk_cache;
|
use flowy_revision::mk_text_block_revision_disk_cache;
|
||||||
use flowy_sync::{client_folder::FolderPad, entities::revision::Revision};
|
use flowy_sync::{client_folder::FolderPad, entities::revision::Revision};
|
||||||
use lib_ot::core::PlainTextDeltaBuilder;
|
use lib_ot::core::TextDeltaBuilder;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
pub use version_1::{app_sql::*, trash_sql::*, v1_impl::V1Transaction, view_sql::*, workspace_sql::*};
|
pub use version_1::{app_sql::*, trash_sql::*, v1_impl::V1Transaction, view_sql::*, workspace_sql::*};
|
||||||
@ -110,7 +110,7 @@ impl FolderPersistence {
|
|||||||
pub async fn save_folder(&self, user_id: &str, folder_id: &FolderId, folder: FolderPad) -> FlowyResult<()> {
|
pub async fn save_folder(&self, user_id: &str, folder_id: &FolderId, folder: FolderPad) -> FlowyResult<()> {
|
||||||
let pool = self.database.db_pool()?;
|
let pool = self.database.db_pool()?;
|
||||||
let json = folder.to_json()?;
|
let json = folder.to_json()?;
|
||||||
let delta_data = PlainTextDeltaBuilder::new().insert(&json).build().to_json_bytes();
|
let delta_data = TextDeltaBuilder::new().insert(&json).build().to_json_bytes();
|
||||||
let revision = Revision::initial_revision(user_id, folder_id.as_ref(), delta_data);
|
let revision = Revision::initial_revision(user_id, folder_id.as_ref(), delta_data);
|
||||||
let record = RevisionRecord {
|
let record = RevisionRecord {
|
||||||
revision,
|
revision,
|
||||||
|
@ -10,7 +10,7 @@ use flowy_sync::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use lib_infra::future::{BoxResultFuture, FutureResult};
|
use lib_infra::future::{BoxResultFuture, FutureResult};
|
||||||
use lib_ot::core::{OperationTransform, PhantomAttributes, PlainTextDelta};
|
use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use std::{sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ struct FolderConflictResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConflictResolver<PhantomAttributes> for FolderConflictResolver {
|
impl ConflictResolver<PhantomAttributes> for FolderConflictResolver {
|
||||||
fn compose_delta(&self, delta: PlainTextDelta) -> BoxResultFuture<DeltaMD5, FlowyError> {
|
fn compose_delta(&self, delta: TextDelta) -> BoxResultFuture<DeltaMD5, FlowyError> {
|
||||||
let folder_pad = self.folder_pad.clone();
|
let folder_pad = self.folder_pad.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let md5 = folder_pad.write().compose_remote_delta(delta)?;
|
let md5 = folder_pad.write().compose_remote_delta(delta)?;
|
||||||
@ -64,15 +64,12 @@ impl ConflictResolver<PhantomAttributes> for FolderConflictResolver {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform_delta(
|
fn transform_delta(&self, delta: TextDelta) -> BoxResultFuture<TransformDeltas<PhantomAttributes>, FlowyError> {
|
||||||
&self,
|
|
||||||
delta: PlainTextDelta,
|
|
||||||
) -> BoxResultFuture<TransformDeltas<PhantomAttributes>, FlowyError> {
|
|
||||||
let folder_pad = self.folder_pad.clone();
|
let folder_pad = self.folder_pad.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let read_guard = folder_pad.read();
|
let read_guard = folder_pad.read();
|
||||||
let mut server_prime: Option<PlainTextDelta> = None;
|
let mut server_prime: Option<TextDelta> = None;
|
||||||
let client_prime: PlainTextDelta;
|
let client_prime: TextDelta;
|
||||||
if read_guard.is_empty() {
|
if read_guard.is_empty() {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
client_prime = delta;
|
client_prime = delta;
|
||||||
@ -89,7 +86,7 @@ impl ConflictResolver<PhantomAttributes> for FolderConflictResolver {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_delta(&self, delta: PlainTextDelta) -> BoxResultFuture<DeltaMD5, FlowyError> {
|
fn reset_delta(&self, delta: TextDelta) -> BoxResultFuture<DeltaMD5, FlowyError> {
|
||||||
let folder_pad = self.folder_pad.clone();
|
let folder_pad = self.folder_pad.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let md5 = folder_pad.write().reset_folder(delta)?;
|
let md5 = folder_pad.write().reset_folder(delta)?;
|
||||||
|
@ -9,7 +9,7 @@ use flowy_revision::{mk_grid_block_revision_disk_cache, RevisionLoader, Revision
|
|||||||
use flowy_sync::client_grid::{make_grid_rev_json_str, GridRevisionPad};
|
use flowy_sync::client_grid::{make_grid_rev_json_str, GridRevisionPad};
|
||||||
use flowy_sync::entities::revision::Revision;
|
use flowy_sync::entities::revision::Revision;
|
||||||
|
|
||||||
use lib_ot::core::PlainTextDeltaBuilder;
|
use lib_ot::core::TextDeltaBuilder;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -48,7 +48,7 @@ impl GridMigration {
|
|||||||
let pool = self.database.db_pool()?;
|
let pool = self.database.db_pool()?;
|
||||||
let grid_rev_pad = self.get_grid_revision_pad(grid_id).await?;
|
let grid_rev_pad = self.get_grid_revision_pad(grid_id).await?;
|
||||||
let json = grid_rev_pad.json_str()?;
|
let json = grid_rev_pad.json_str()?;
|
||||||
let delta_data = PlainTextDeltaBuilder::new().insert(&json).build().to_json_bytes();
|
let delta_data = TextDeltaBuilder::new().insert(&json).build().to_json_bytes();
|
||||||
let revision = Revision::initial_revision(&user_id, grid_id, delta_data);
|
let revision = Revision::initial_revision(&user_id, grid_id, delta_data);
|
||||||
let record = RevisionRecord::new(revision);
|
let record = RevisionRecord::new(revision);
|
||||||
//
|
//
|
||||||
|
@ -342,11 +342,8 @@ fn apply_1000() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn apply_test() {
|
fn apply_test() {
|
||||||
let s = "hello";
|
let s = "hello";
|
||||||
let delta_a = PlainTextDeltaBuilder::new().insert(s).build();
|
let delta_a = TextDeltaBuilder::new().insert(s).build();
|
||||||
let delta_b = PlainTextDeltaBuilder::new()
|
let delta_b = TextDeltaBuilder::new().retain(s.len()).insert(", AppFlowy").build();
|
||||||
.retain(s.len())
|
|
||||||
.insert(", AppFlowy")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let after_a = delta_a.content_str().unwrap();
|
let after_a = delta_a.content_str().unwrap();
|
||||||
let after_b = delta_b.apply(&after_a).unwrap();
|
let after_b = delta_b.apply(&after_a).unwrap();
|
||||||
@ -384,7 +381,7 @@ fn invert() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn invert_test() {
|
fn invert_test() {
|
||||||
let s = "hello world";
|
let s = "hello world";
|
||||||
let delta = PlainTextDeltaBuilder::new().insert(s).build();
|
let delta = TextDeltaBuilder::new().insert(s).build();
|
||||||
let invert_delta = delta.invert_str("");
|
let invert_delta = delta.invert_str("");
|
||||||
assert_eq!(delta.utf16_base_len, invert_delta.utf16_target_len);
|
assert_eq!(delta.utf16_base_len, invert_delta.utf16_target_len);
|
||||||
assert_eq!(delta.utf16_target_len, invert_delta.utf16_base_len);
|
assert_eq!(delta.utf16_target_len, invert_delta.utf16_base_len);
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use flowy_folder_data_model::revision::{TrashRevision, WorkspaceRevision};
|
use flowy_folder_data_model::revision::{TrashRevision, WorkspaceRevision};
|
||||||
use lib_ot::core::{PhantomAttributes, PlainTextDelta, PlainTextDeltaBuilder};
|
use lib_ot::core::{PhantomAttributes, TextDelta, TextDeltaBuilder};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ impl FolderPadBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn build_with_delta(self, mut delta: PlainTextDelta) -> CollaborateResult<FolderPad> {
|
pub(crate) fn build_with_delta(self, mut delta: TextDelta) -> CollaborateResult<FolderPad> {
|
||||||
if delta.is_empty() {
|
if delta.is_empty() {
|
||||||
delta = default_folder_delta();
|
delta = default_folder_delta();
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ impl FolderPadBuilder {
|
|||||||
Ok(FolderPad {
|
Ok(FolderPad {
|
||||||
workspaces: self.workspaces,
|
workspaces: self.workspaces,
|
||||||
trash: self.trash,
|
trash: self.trash,
|
||||||
delta: PlainTextDeltaBuilder::new().insert(&json).build(),
|
delta: TextDeltaBuilder::new().insert(&json).build(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,14 +400,14 @@ impl FolderPad {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_folder_delta() -> FolderDelta {
|
pub fn default_folder_delta() -> FolderDelta {
|
||||||
PlainTextDeltaBuilder::new()
|
TextDeltaBuilder::new()
|
||||||
.insert(r#"{"workspaces":[],"trash":[]}"#)
|
.insert(r#"{"workspaces":[],"trash":[]}"#)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initial_folder_delta(folder_pad: &FolderPad) -> CollaborateResult<FolderDelta> {
|
pub fn initial_folder_delta(folder_pad: &FolderPad) -> CollaborateResult<FolderDelta> {
|
||||||
let json = folder_pad.to_json()?;
|
let json = folder_pad.to_json()?;
|
||||||
let delta = PlainTextDeltaBuilder::new().insert(&json).build();
|
let delta = TextDeltaBuilder::new().insert(&json).build();
|
||||||
Ok(delta)
|
Ok(delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +434,7 @@ mod tests {
|
|||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
|
|
||||||
use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision, WorkspaceRevision};
|
use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision, WorkspaceRevision};
|
||||||
use lib_ot::core::{OperationTransform, PlainTextDelta, PlainTextDeltaBuilder};
|
use lib_ot::core::{OperationTransform, TextDelta, TextDeltaBuilder};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn folder_add_workspace() {
|
fn folder_add_workspace() {
|
||||||
@ -749,7 +749,7 @@ mod tests {
|
|||||||
fn test_folder() -> (FolderPad, FolderDelta, WorkspaceRevision) {
|
fn test_folder() -> (FolderPad, FolderDelta, WorkspaceRevision) {
|
||||||
let mut folder = FolderPad::default();
|
let mut folder = FolderPad::default();
|
||||||
let folder_json = serde_json::to_string(&folder).unwrap();
|
let folder_json = serde_json::to_string(&folder).unwrap();
|
||||||
let mut delta = PlainTextDeltaBuilder::new().insert(&folder_json).build();
|
let mut delta = TextDeltaBuilder::new().insert(&folder_json).build();
|
||||||
|
|
||||||
let mut workspace_rev = WorkspaceRevision::default();
|
let mut workspace_rev = WorkspaceRevision::default();
|
||||||
workspace_rev.name = "😁 my first workspace".to_owned();
|
workspace_rev.name = "😁 my first workspace".to_owned();
|
||||||
@ -791,7 +791,7 @@ mod tests {
|
|||||||
fn test_trash() -> (FolderPad, FolderDelta, TrashRevision) {
|
fn test_trash() -> (FolderPad, FolderDelta, TrashRevision) {
|
||||||
let mut folder = FolderPad::default();
|
let mut folder = FolderPad::default();
|
||||||
let folder_json = serde_json::to_string(&folder).unwrap();
|
let folder_json = serde_json::to_string(&folder).unwrap();
|
||||||
let mut delta = PlainTextDeltaBuilder::new().insert(&folder_json).build();
|
let mut delta = TextDeltaBuilder::new().insert(&folder_json).build();
|
||||||
|
|
||||||
let mut trash_rev = TrashRevision::default();
|
let mut trash_rev = TrashRevision::default();
|
||||||
trash_rev.name = "🚽 my first trash".to_owned();
|
trash_rev.name = "🚽 my first trash".to_owned();
|
||||||
@ -810,7 +810,7 @@ mod tests {
|
|||||||
(folder, delta, trash_rev)
|
(folder, delta, trash_rev)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_folder_from_delta(mut initial_delta: FolderDelta, deltas: Vec<PlainTextDelta>) -> FolderPad {
|
fn make_folder_from_delta(mut initial_delta: FolderDelta, deltas: Vec<TextDelta>) -> FolderPad {
|
||||||
for delta in deltas {
|
for delta in deltas {
|
||||||
initial_delta = initial_delta.compose(&delta).unwrap();
|
initial_delta = initial_delta.compose(&delta).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@ use crate::util::{cal_diff, make_delta_from_revisions};
|
|||||||
use flowy_grid_data_model::revision::{
|
use flowy_grid_data_model::revision::{
|
||||||
gen_block_id, gen_row_id, CellRevision, GridBlockRevision, RowMetaChangeset, RowRevision,
|
gen_block_id, gen_row_id, CellRevision, GridBlockRevision, RowMetaChangeset, RowRevision,
|
||||||
};
|
};
|
||||||
use lib_ot::core::{OperationTransform, PhantomAttributes, PlainTextDelta, PlainTextDeltaBuilder};
|
use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta, TextDeltaBuilder};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub type GridBlockRevisionDelta = PlainTextDelta;
|
pub type GridBlockRevisionDelta = TextDelta;
|
||||||
pub type GridBlockRevisionDeltaBuilder = PlainTextDeltaBuilder;
|
pub type GridBlockRevisionDeltaBuilder = TextDeltaBuilder;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct GridBlockRevisionPad {
|
pub struct GridBlockRevisionPad {
|
||||||
@ -247,7 +247,7 @@ pub struct GridBlockMetaChange {
|
|||||||
|
|
||||||
pub fn make_grid_block_delta(block_rev: &GridBlockRevision) -> GridBlockRevisionDelta {
|
pub fn make_grid_block_delta(block_rev: &GridBlockRevision) -> GridBlockRevisionDelta {
|
||||||
let json = serde_json::to_string(&block_rev).unwrap();
|
let json = serde_json::to_string(&block_rev).unwrap();
|
||||||
PlainTextDeltaBuilder::new().insert(&json).build()
|
TextDeltaBuilder::new().insert(&json).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_grid_block_revisions(user_id: &str, grid_block_meta_data: &GridBlockRevision) -> RepeatedRevision {
|
pub fn make_grid_block_revisions(user_id: &str, grid_block_meta_data: &GridBlockRevision) -> RepeatedRevision {
|
||||||
|
@ -9,12 +9,12 @@ use flowy_grid_data_model::revision::{
|
|||||||
GridLayoutRevision, GridRevision, GridSettingRevision, GridSortRevision,
|
GridLayoutRevision, GridRevision, GridSettingRevision, GridSortRevision,
|
||||||
};
|
};
|
||||||
use lib_infra::util::move_vec_element;
|
use lib_infra::util::move_vec_element;
|
||||||
use lib_ot::core::{OperationTransform, PhantomAttributes, PlainTextDelta, PlainTextDeltaBuilder};
|
use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta, TextDeltaBuilder};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub type GridRevisionDelta = PlainTextDelta;
|
pub type GridRevisionDelta = TextDelta;
|
||||||
pub type GridRevisionDeltaBuilder = PlainTextDeltaBuilder;
|
pub type GridRevisionDeltaBuilder = TextDeltaBuilder;
|
||||||
|
|
||||||
pub struct GridRevisionPad {
|
pub struct GridRevisionPad {
|
||||||
grid_rev: Arc<GridRevision>,
|
grid_rev: Arc<GridRevision>,
|
||||||
@ -548,7 +548,7 @@ pub struct GridChangeset {
|
|||||||
|
|
||||||
pub fn make_grid_delta(grid_rev: &GridRevision) -> GridRevisionDelta {
|
pub fn make_grid_delta(grid_rev: &GridRevision) -> GridRevisionDelta {
|
||||||
let json = serde_json::to_string(&grid_rev).unwrap();
|
let json = serde_json::to_string(&grid_rev).unwrap();
|
||||||
PlainTextDeltaBuilder::new().insert(&json).build()
|
TextDeltaBuilder::new().insert(&json).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_grid_revisions(user_id: &str, grid_rev: &GridRevision) -> RepeatedRevision {
|
pub fn make_grid_revisions(user_id: &str, grid_rev: &GridRevision) -> RepeatedRevision {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use lib_ot::core::PlainTextDelta;
|
use lib_ot::core::TextDelta;
|
||||||
|
|
||||||
pub type FolderDelta = PlainTextDelta;
|
pub type FolderDelta = TextDelta;
|
||||||
|
|
||||||
#[derive(ProtoBuf, Default, Debug, Clone, Eq, PartialEq)]
|
#[derive(ProtoBuf, Default, Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct FolderInfo {
|
pub struct FolderInfo {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{entities::folder::FolderDelta, errors::CollaborateError, synchronizer::RevisionSyncObject};
|
use crate::{entities::folder::FolderDelta, errors::CollaborateError, synchronizer::RevisionSyncObject};
|
||||||
use lib_ot::core::{OperationTransform, PhantomAttributes, PlainTextDelta};
|
use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta};
|
||||||
|
|
||||||
pub struct ServerFolder {
|
pub struct ServerFolder {
|
||||||
folder_id: String,
|
folder_id: String,
|
||||||
@ -20,13 +20,13 @@ impl RevisionSyncObject<PhantomAttributes> for ServerFolder {
|
|||||||
&self.folder_id
|
&self.folder_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compose(&mut self, other: &PlainTextDelta) -> Result<(), CollaborateError> {
|
fn compose(&mut self, other: &TextDelta) -> Result<(), CollaborateError> {
|
||||||
let new_delta = self.delta.compose(other)?;
|
let new_delta = self.delta.compose(other)?;
|
||||||
self.delta = new_delta;
|
self.delta = new_delta;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform(&self, other: &PlainTextDelta) -> Result<(PlainTextDelta, PlainTextDelta), CollaborateError> {
|
fn transform(&self, other: &TextDelta) -> Result<(TextDelta, TextDelta), CollaborateError> {
|
||||||
let value = self.delta.transform(other)?;
|
let value = self.delta.transform(other)?;
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ impl RevisionSyncObject<PhantomAttributes> for ServerFolder {
|
|||||||
self.delta.to_json_str()
|
self.delta.to_json_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_delta(&mut self, new_delta: PlainTextDelta) {
|
fn set_delta(&mut self, new_delta: TextDelta) {
|
||||||
self.delta = new_delta;
|
self.delta = new_delta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use crate::core::delta::{trim, Delta};
|
use crate::core::delta::{trim, Delta};
|
||||||
use crate::core::operation::{Attributes, PhantomAttributes};
|
use crate::core::operation::Attributes;
|
||||||
use crate::core::Operation;
|
use crate::core::Operation;
|
||||||
|
|
||||||
pub type PlainTextDeltaBuilder = DeltaBuilder<PhantomAttributes>;
|
|
||||||
|
|
||||||
/// A builder for creating new [Delta] objects.
|
/// A builder for creating new [Delta] objects.
|
||||||
///
|
///
|
||||||
/// Note that all edit operations must be sorted; the start point of each
|
/// Note that all edit operations must be sorted; the start point of each
|
||||||
@ -12,8 +10,8 @@ pub type PlainTextDeltaBuilder = DeltaBuilder<PhantomAttributes>;
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib_ot::core::PlainTextDeltaBuilder;
|
/// use lib_ot::core::TextDeltaBuilder;
|
||||||
/// let delta = PlainTextDeltaBuilder::new()
|
/// let delta = TextDeltaBuilder::new()
|
||||||
/// .insert("AppFlowy")
|
/// .insert("AppFlowy")
|
||||||
/// .build();
|
/// .build();
|
||||||
/// assert_eq!(delta.content_str().unwrap(), "AppFlowy");
|
/// assert_eq!(delta.content_str().unwrap(), "AppFlowy");
|
||||||
@ -74,13 +72,13 @@ where
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib_ot::core::{OperationTransform, PlainTextDeltaBuilder};
|
/// use lib_ot::core::{OperationTransform, TextDeltaBuilder};
|
||||||
///
|
///
|
||||||
/// let delta = PlainTextDeltaBuilder::new()
|
/// let delta = TextDeltaBuilder::new()
|
||||||
/// .insert("AppFlowy...")
|
/// .insert("AppFlowy...")
|
||||||
/// .build();
|
/// .build();
|
||||||
///
|
///
|
||||||
/// let changeset = PlainTextDeltaBuilder::new()
|
/// let changeset = TextDeltaBuilder::new()
|
||||||
/// .retain(8)
|
/// .retain(8)
|
||||||
/// .delete(3)
|
/// .delete(3)
|
||||||
/// .build();
|
/// .build();
|
||||||
@ -110,9 +108,9 @@ where
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib_ot::core::{OperationTransform, PlainTextDeltaBuilder};
|
/// use lib_ot::core::{OperationTransform, TextDeltaBuilder};
|
||||||
/// use lib_ot::rich_text::{RichTextAttribute, RichTextDeltaBuilder};
|
/// use lib_ot::rich_text::{RichTextAttribute, RichTextDeltaBuilder};
|
||||||
/// let delta = PlainTextDeltaBuilder::new()
|
/// let delta = TextDeltaBuilder::new()
|
||||||
/// .retain(3)
|
/// .retain(3)
|
||||||
/// .trim()
|
/// .trim()
|
||||||
/// .build();
|
/// .build();
|
||||||
|
@ -29,14 +29,17 @@ where
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib_ot::core::{DeltaIterator, Interval, Operation};
|
/// use lib_ot::core::{DeltaCursor, DeltaIterator, Interval, Operation};
|
||||||
/// use lib_ot::rich_text::RichTextDelta;
|
/// use lib_ot::rich_text::RichTextDelta;
|
||||||
/// let mut delta = RichTextDelta::default();
|
/// let mut delta = RichTextDelta::default();
|
||||||
/// let op_1 = Operation::insert("123");
|
/// delta.add(Operation::insert("123"));
|
||||||
/// let op_2 = Operation::insert("4");
|
/// delta.add(Operation::insert("4"));
|
||||||
/// delta.add(op_1.clone());
|
///
|
||||||
/// delta.add(op_2.clone());
|
/// let mut cursor = DeltaCursor::new(&delta, Interval::new(0, 3));
|
||||||
/// assert_eq!(DeltaIterator::from_interval(&delta, Interval::new(0, 3)).ops(), vec![op_1.clone()]);
|
/// assert_eq!(cursor.next_iv(), Interval::new(0,3));
|
||||||
|
/// assert_eq!(cursor.next_with_len(Some(2)).unwrap(), Operation::insert("12"));
|
||||||
|
/// assert_eq!(cursor.get_next_op().unwrap(), Operation::insert("3"));
|
||||||
|
/// assert_eq!(cursor.get_next_op(), None);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(delta: &'a Delta<T>, interval: Interval) -> DeltaCursor<'a, T> {
|
pub fn new(delta: &'a Delta<T>, interval: Interval) -> DeltaCursor<'a, T> {
|
||||||
// debug_assert!(interval.start <= delta.target_len);
|
// debug_assert!(interval.start <= delta.target_len);
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use crate::errors::{ErrorBuilder, OTError, OTErrorCode};
|
use crate::errors::{ErrorBuilder, OTError, OTErrorCode};
|
||||||
|
|
||||||
use crate::core::delta::{DeltaIterator, MAX_IV_LEN};
|
use crate::core::delta::{DeltaIterator, MAX_IV_LEN};
|
||||||
use crate::core::flowy_str::OTString;
|
|
||||||
use crate::core::interval::Interval;
|
use crate::core::interval::Interval;
|
||||||
use crate::core::operation::{Attributes, Operation, OperationTransform, PhantomAttributes};
|
use crate::core::operation::{Attributes, Operation, OperationTransform, PhantomAttributes};
|
||||||
|
use crate::core::ot_str::OTString;
|
||||||
|
use crate::core::DeltaBuilder;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use std::{
|
use std::{
|
||||||
@ -14,12 +15,15 @@ use std::{
|
|||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type PlainTextDelta = Delta<PhantomAttributes>;
|
pub type TextDelta = Delta<PhantomAttributes>;
|
||||||
|
pub type TextDeltaBuilder = DeltaBuilder<PhantomAttributes>;
|
||||||
|
|
||||||
/// A [Delta] contains list of operations that consists of 'Retain', 'Delete' and 'Insert' operation.
|
/// A [Delta] contains list of operations that consists of 'Retain', 'Delete' and 'Insert' operation.
|
||||||
/// Check out the [Operation] for more details. It describes the document as a sequence of
|
/// Check out the [Operation] for more details. It describes the document as a sequence of
|
||||||
/// operations.
|
/// operations.
|
||||||
///
|
///
|
||||||
|
/// You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/backend/delta) out for more information.
|
||||||
|
///
|
||||||
/// If the [T] supports 'serde', that will enable delta to serialize to JSON or deserialize from
|
/// If the [T] supports 'serde', that will enable delta to serialize to JSON or deserialize from
|
||||||
/// a JSON string.
|
/// a JSON string.
|
||||||
///
|
///
|
||||||
@ -176,10 +180,10 @@ where
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib_ot::core::PlainTextDeltaBuilder;
|
/// use lib_ot::core::TextDeltaBuilder;
|
||||||
/// let s = "hello";
|
/// let s = "hello";
|
||||||
/// let delta_a = PlainTextDeltaBuilder::new().insert(s).build();
|
/// let delta_a = TextDeltaBuilder::new().insert(s).build();
|
||||||
/// let delta_b = PlainTextDeltaBuilder::new()
|
/// let delta_b = TextDeltaBuilder::new()
|
||||||
/// .retain(s.len())
|
/// .retain(s.len())
|
||||||
/// .insert(", AppFlowy")
|
/// .insert(", AppFlowy")
|
||||||
/// .build();
|
/// .build();
|
||||||
@ -233,9 +237,9 @@ where
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib_ot::core::PlainTextDeltaBuilder;
|
/// use lib_ot::core::TextDeltaBuilder;
|
||||||
/// let s = "hello world";
|
/// let s = "hello world";
|
||||||
/// let delta = PlainTextDeltaBuilder::new().insert(s).build();
|
/// let delta = TextDeltaBuilder::new().insert(s).build();
|
||||||
/// let invert_delta = delta.invert_str(s);
|
/// let invert_delta = delta.invert_str(s);
|
||||||
/// assert_eq!(delta.utf16_base_len, invert_delta.utf16_target_len);
|
/// assert_eq!(delta.utf16_base_len, invert_delta.utf16_target_len);
|
||||||
/// assert_eq!(delta.utf16_target_len, invert_delta.utf16_base_len);
|
/// assert_eq!(delta.utf16_target_len, invert_delta.utf16_base_len);
|
||||||
|
@ -7,17 +7,26 @@ use std::ops::{Deref, DerefMut};
|
|||||||
|
|
||||||
pub(crate) const MAX_IV_LEN: usize = i32::MAX as usize;
|
pub(crate) const MAX_IV_LEN: usize = i32::MAX as usize;
|
||||||
|
|
||||||
/// Retain the 'n' characters with the attributes. Use 'retain' instead if you don't
|
/// [DeltaIterator] is used to iterate over a delta.
|
||||||
/// need any attributes.
|
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
/// You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/backend/delta) out for more information.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib_ot::rich_text::{RichTextAttribute, RichTextDelta, RichTextDeltaBuilder};
|
/// use lib_ot::core::{DeltaIterator, Interval, Operation};
|
||||||
|
/// use lib_ot::rich_text::RichTextDelta;
|
||||||
|
/// let mut delta = RichTextDelta::default();
|
||||||
|
/// delta.add(Operation::insert("123"));
|
||||||
|
/// delta.add(Operation::insert("4"));
|
||||||
|
/// assert_eq!(
|
||||||
|
/// DeltaIterator::from_interval(&delta, Interval::new(0, 2)).ops(),
|
||||||
|
/// vec![Operation::insert("12")]
|
||||||
|
/// );
|
||||||
///
|
///
|
||||||
/// let mut attribute = RichTextAttribute::Bold(true);
|
/// assert_eq!(
|
||||||
/// let delta = RichTextDeltaBuilder::new().retain_with_attributes(7, attribute.into()).build();
|
/// DeltaIterator::from_interval(&delta, Interval::new(1, 3)).ops(),
|
||||||
///
|
/// vec![Operation::insert("23")]
|
||||||
/// assert_eq!(delta.to_json_str(), r#"[{"retain":7,"attributes":{"bold":true}}]"#);
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
pub struct DeltaIterator<'a, T: Attributes> {
|
pub struct DeltaIterator<'a, T: Attributes> {
|
||||||
cursor: DeltaCursor<'a, T>,
|
cursor: DeltaCursor<'a, T>,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
mod delta;
|
mod delta;
|
||||||
mod flowy_str;
|
|
||||||
mod interval;
|
mod interval;
|
||||||
mod operation;
|
mod operation;
|
||||||
|
mod ot_str;
|
||||||
|
|
||||||
pub use delta::*;
|
pub use delta::*;
|
||||||
pub use flowy_str::*;
|
|
||||||
pub use interval::*;
|
pub use interval::*;
|
||||||
pub use operation::*;
|
pub use operation::*;
|
||||||
|
pub use ot_str::*;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::core::flowy_str::OTString;
|
|
||||||
use crate::core::interval::Interval;
|
use crate::core::interval::Interval;
|
||||||
|
use crate::core::ot_str::OTString;
|
||||||
use crate::errors::OTError;
|
use crate::errors::OTError;
|
||||||
use serde::{Deserialize, Serialize, __private::Formatter};
|
use serde::{Deserialize, Serialize, __private::Formatter};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
@ -21,9 +21,9 @@ pub trait OperationTransform {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib_ot::core::{OperationTransform, PlainTextDeltaBuilder};
|
/// use lib_ot::core::{OperationTransform, TextDeltaBuilder};
|
||||||
/// let document = PlainTextDeltaBuilder::new().build();
|
/// let document = TextDeltaBuilder::new().build();
|
||||||
/// let delta = PlainTextDeltaBuilder::new().insert("abc").build();
|
/// let delta = TextDeltaBuilder::new().insert("abc").build();
|
||||||
/// let new_document = document.compose(&delta).unwrap();
|
/// let new_document = document.compose(&delta).unwrap();
|
||||||
/// assert_eq!(new_document.content_str().unwrap(), "abc".to_owned());
|
/// assert_eq!(new_document.content_str().unwrap(), "abc".to_owned());
|
||||||
/// ```
|
/// ```
|
||||||
@ -50,9 +50,9 @@ pub trait OperationTransform {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib_ot::core::{OperationTransform, PlainTextDeltaBuilder};
|
/// use lib_ot::core::{OperationTransform, TextDeltaBuilder};
|
||||||
/// let original_document = PlainTextDeltaBuilder::new().build();
|
/// let original_document = TextDeltaBuilder::new().build();
|
||||||
/// let delta = PlainTextDeltaBuilder::new().insert("abc").build();
|
/// let delta = TextDeltaBuilder::new().insert("abc").build();
|
||||||
///
|
///
|
||||||
/// let undo_delta = delta.invert(&original_document);
|
/// let undo_delta = delta.invert(&original_document);
|
||||||
/// let new_document = original_document.compose(&delta).unwrap();
|
/// let new_document = original_document.compose(&delta).unwrap();
|
||||||
@ -67,8 +67,8 @@ pub trait OperationTransform {
|
|||||||
/// Each operation can carry attributes. For example, the [RichTextAttributes] has a list of key/value attributes.
|
/// Each operation can carry attributes. For example, the [RichTextAttributes] has a list of key/value attributes.
|
||||||
/// Such as { bold: true, italic: true }.
|
/// Such as { bold: true, italic: true }.
|
||||||
///
|
///
|
||||||
/// Because [Operation] is generic over the T, so you must specify the T. For example, the [PlainTextDelta]. It use
|
///Because [Operation] is generic over the T, so you must specify the T. For example, the [TextDelta] uses
|
||||||
/// use [PhantomAttributes] as the T. [PhantomAttributes] does nothing, just a phantom.
|
///[PhantomAttributes] as the T. [PhantomAttributes] does nothing, just a phantom.
|
||||||
///
|
///
|
||||||
pub trait Attributes: Default + Display + Eq + PartialEq + Clone + Debug + OperationTransform {
|
pub trait Attributes: Default + Display + Eq + PartialEq + Clone + Debug + OperationTransform {
|
||||||
fn is_empty(&self) -> bool {
|
fn is_empty(&self) -> bool {
|
||||||
@ -90,6 +90,8 @@ pub trait Attributes: Default + Display + Eq + PartialEq + Clone + Debug + Opera
|
|||||||
/// * Retain
|
/// * Retain
|
||||||
/// * Insert
|
/// * Insert
|
||||||
///
|
///
|
||||||
|
/// You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/backend/delta) out for more information.
|
||||||
|
///
|
||||||
/// The [T] should support serde if you want to serialize/deserialize the operation
|
/// The [T] should support serde if you want to serialize/deserialize the operation
|
||||||
/// to json string. You could check out the operation_serde.rs for more information.
|
/// to json string. You could check out the operation_serde.rs for more information.
|
||||||
///
|
///
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::core::flowy_str::OTString;
|
|
||||||
use crate::core::operation::{Attributes, Insert, Operation, Retain};
|
use crate::core::operation::{Attributes, Insert, Operation, Retain};
|
||||||
|
use crate::core::ot_str::OTString;
|
||||||
use serde::{
|
use serde::{
|
||||||
de,
|
de,
|
||||||
de::{MapAccess, SeqAccess, Visitor},
|
de::{MapAccess, SeqAccess, Visitor},
|
||||||
|
@ -86,8 +86,8 @@ impl OTString {
|
|||||||
/// assert_eq!(iter.skip(OTString::from("ab一二").utf16_len()).next().unwrap(), "👋".to_string());
|
/// assert_eq!(iter.skip(OTString::from("ab一二").utf16_len()).next().unwrap(), "👋".to_string());
|
||||||
/// ```
|
/// ```
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn utf16_code_point_iter(&self) -> FlowyUtf16CodePointIterator {
|
pub fn utf16_code_point_iter(&self) -> OTUtf16CodePointIterator {
|
||||||
FlowyUtf16CodePointIterator::new(self, 0)
|
OTUtf16CodePointIterator::new(self, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,21 +218,21 @@ impl<'a> Iterator for Utf16CodeUnitIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FlowyUtf16CodePointIterator<'a> {
|
pub struct OTUtf16CodePointIterator<'a> {
|
||||||
s: &'a OTString,
|
s: &'a OTString,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FlowyUtf16CodePointIterator<'a> {
|
impl<'a> OTUtf16CodePointIterator<'a> {
|
||||||
pub fn new(s: &'a OTString, offset: usize) -> Self {
|
pub fn new(s: &'a OTString, offset: usize) -> Self {
|
||||||
FlowyUtf16CodePointIterator { s, offset }
|
OTUtf16CodePointIterator { s, offset }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::core::interval::Interval;
|
use crate::core::interval::Interval;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
impl<'a> Iterator for FlowyUtf16CodePointIterator<'a> {
|
impl<'a> Iterator for OTUtf16CodePointIterator<'a> {
|
||||||
type Item = String;
|
type Item = String;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
@ -278,8 +278,8 @@ pub fn len_utf8_from_first_byte(b: u8) -> usize {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::core::flowy_str::OTString;
|
|
||||||
use crate::core::interval::Interval;
|
use crate::core::interval::Interval;
|
||||||
|
use crate::core::ot_str::OTString;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn flowy_str_code_unit() {
|
fn flowy_str_code_unit() {
|
Loading…
Reference in New Issue
Block a user