From 798e16d3aa7589dbc05a9475139f75f6bfab0851 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 1 Aug 2022 09:31:40 +0800 Subject: [PATCH 1/3] chore: update lib ot tests --- .../flowy-folder/src/services/web_socket.rs | 2 +- .../rust-lib/flowy-text-block/src/queue.rs | 2 +- .../tests/editor/attribute_test.rs | 4 +- .../flowy-text-block/tests/editor/mod.rs | 2 +- .../flowy-text-block/tests/editor/op_test.rs | 15 ++--- .../src/client_folder/folder_pad.rs | 2 +- .../src/client_grid/grid_block_revsion_pad.rs | 2 +- .../src/client_grid/grid_revision_pad.rs | 2 +- .../src/server_folder/folder_pad.rs | 2 +- shared-lib/flowy-sync/src/util.rs | 6 +- shared-lib/lib-ot/src/core/delta/builder.rs | 66 +++++++++++++++++++ shared-lib/lib-ot/src/core/delta/delta.rs | 21 ++++-- shared-lib/lib-ot/src/core/delta/iterator.rs | 12 ++++ shared-lib/lib-ot/src/core/flowy_str.rs | 28 ++++++-- .../lib-ot/src/core/operation/builder.rs | 50 +++++++------- .../lib-ot/src/core/operation/operation.rs | 12 ++-- shared-lib/lib-ot/src/rich_text/attributes.rs | 4 +- 17 files changed, 170 insertions(+), 62 deletions(-) diff --git a/frontend/rust-lib/flowy-folder/src/services/web_socket.rs b/frontend/rust-lib/flowy-folder/src/services/web_socket.rs index eac429dc1f..4b5481c9a0 100644 --- a/frontend/rust-lib/flowy-folder/src/services/web_socket.rs +++ b/frontend/rust-lib/flowy-folder/src/services/web_socket.rs @@ -10,7 +10,7 @@ use flowy_sync::{ }, }; use lib_infra::future::{BoxResultFuture, FutureResult}; -use lib_ot::core::{OperationTransformable, PhantomAttributes, PlainTextDelta}; +use lib_ot::core::{OperationTransform, PhantomAttributes, PlainTextDelta}; use parking_lot::RwLock; use std::{sync::Arc, time::Duration}; diff --git a/frontend/rust-lib/flowy-text-block/src/queue.rs b/frontend/rust-lib/flowy-text-block/src/queue.rs index 072c810d9d..8756a50a00 100644 --- a/frontend/rust-lib/flowy-text-block/src/queue.rs +++ b/frontend/rust-lib/flowy-text-block/src/queue.rs @@ -12,7 +12,7 @@ use flowy_sync::{ }; use futures::stream::StreamExt; use lib_ot::{ - core::{Interval, OperationTransformable}, + core::{Interval, OperationTransform}, rich_text::{RichTextAttribute, RichTextAttributes, RichTextDelta}, }; use std::sync::Arc; diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs b/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs index 6dcd372d47..bdeb1601b9 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs @@ -1,7 +1,7 @@ #![cfg_attr(rustfmt, rustfmt::skip)] use crate::editor::{TestBuilder, TestOp::*}; use flowy_sync::client_document::{NewlineDoc, PlainDoc}; -use lib_ot::core::{Interval, OperationTransformable, NEW_LINE, WHITESPACE, FlowyStr}; +use lib_ot::core::{Interval, OperationTransform, NEW_LINE, WHITESPACE, FlowyStr}; use unicode_segmentation::UnicodeSegmentation; use lib_ot::rich_text::RichTextDelta; @@ -724,7 +724,7 @@ fn attributes_preserve_header_format_on_merge() { fn attributes_format_emoji() { let emoji_s = "πŸ‘‹ "; let s: FlowyStr = emoji_s.into(); - let len = s.utf16_size(); + let len = s.utf16_len(); assert_eq!(3, len); assert_eq!(2, s.graphemes(true).count()); diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs b/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs index a6b58ab39b..64f432a1e7 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs @@ -302,7 +302,7 @@ impl Rng { let mut delta = RichTextDelta::default(); let s = FlowyStr::from(s); loop { - let left = s.utf16_size() - delta.utf16_base_len; + let left = s.utf16_len() - delta.utf16_base_len; if left == 0 { break; } diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs b/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs index f32e70942f..20bb14c063 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs @@ -1,6 +1,7 @@ #![allow(clippy::all)] use crate::editor::{Rng, TestBuilder, TestOp::*}; use flowy_sync::client_document::{NewlineDoc, PlainDoc}; +use lib_ot::rich_text::RichTextDeltaBuilder; use lib_ot::{ core::Interval, core::*, @@ -39,12 +40,8 @@ fn attributes_insert_text_at_middle() { #[test] fn delta_get_ops_in_interval_1() { - let mut delta = RichTextDelta::default(); - let insert_a = OperationBuilder::insert("123").build(); - let insert_b = OperationBuilder::insert("4").build(); - - delta.add(insert_a.clone()); - delta.add(insert_b.clone()); + let operations = OperationBuilder::new().insert("123", None).insert("4", None).build(); + let delta = RichTextDeltaBuilder::from_operations(operations); let mut iterator = DeltaIterator::from_interval(&delta, Interval::new(0, 4)); assert_eq!(iterator.ops(), delta.ops); @@ -365,7 +362,7 @@ fn apply_1000() { let mut rng = Rng::default(); let s: FlowyStr = rng.gen_string(50).into(); let delta = rng.gen_delta(&s); - assert_eq!(s.utf16_size(), delta.utf16_base_len); + assert_eq!(s.utf16_len(), delta.utf16_base_len); } } @@ -489,11 +486,11 @@ fn compose() { let s = rng.gen_string(20); let a = rng.gen_delta(&s); let after_a: FlowyStr = a.apply(&s).unwrap().into(); - assert_eq!(a.utf16_target_len, after_a.utf16_size()); + assert_eq!(a.utf16_target_len, after_a.utf16_len()); let b = rng.gen_delta(&after_a); let after_b: FlowyStr = b.apply(&after_a).unwrap().into(); - assert_eq!(b.utf16_target_len, after_b.utf16_size()); + assert_eq!(b.utf16_target_len, after_b.utf16_len()); let ab = a.compose(&b).unwrap(); assert_eq!(ab.utf16_target_len, b.utf16_target_len); diff --git a/shared-lib/flowy-sync/src/client_folder/folder_pad.rs b/shared-lib/flowy-sync/src/client_folder/folder_pad.rs index 0cbc33598e..632aa7f29b 100644 --- a/shared-lib/flowy-sync/src/client_folder/folder_pad.rs +++ b/shared-lib/flowy-sync/src/client_folder/folder_pad.rs @@ -434,7 +434,7 @@ mod tests { use chrono::Utc; use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision, WorkspaceRevision}; - use lib_ot::core::{OperationTransformable, PlainTextDelta, PlainTextDeltaBuilder}; + use lib_ot::core::{OperationTransform, PlainTextDelta, PlainTextDeltaBuilder}; #[test] fn folder_add_workspace() { diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_revsion_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_revsion_pad.rs index cea6d7fd03..82fb19cb8b 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_revsion_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_revsion_pad.rs @@ -4,7 +4,7 @@ use crate::util::{cal_diff, make_delta_from_revisions}; use flowy_grid_data_model::revision::{ gen_block_id, gen_row_id, CellRevision, GridBlockRevision, RowMetaChangeset, RowRevision, }; -use lib_ot::core::{OperationTransformable, PhantomAttributes, PlainTextDelta, PlainTextDeltaBuilder}; +use lib_ot::core::{OperationTransform, PhantomAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs index d1232a261d..9aee7cfedd 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs @@ -9,7 +9,7 @@ use flowy_grid_data_model::revision::{ GridLayoutRevision, GridRevision, GridSettingRevision, GridSortRevision, }; use lib_infra::util::move_vec_element; -use lib_ot::core::{OperationTransformable, PhantomAttributes, PlainTextDelta, PlainTextDeltaBuilder}; +use lib_ot::core::{OperationTransform, PhantomAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use std::collections::HashMap; use std::sync::Arc; diff --git a/shared-lib/flowy-sync/src/server_folder/folder_pad.rs b/shared-lib/flowy-sync/src/server_folder/folder_pad.rs index 29457eb65e..2ff3d0e479 100644 --- a/shared-lib/flowy-sync/src/server_folder/folder_pad.rs +++ b/shared-lib/flowy-sync/src/server_folder/folder_pad.rs @@ -1,5 +1,5 @@ use crate::{entities::folder::FolderDelta, errors::CollaborateError, synchronizer::RevisionSyncObject}; -use lib_ot::core::{OperationTransformable, PhantomAttributes, PlainTextDelta}; +use lib_ot::core::{OperationTransform, PhantomAttributes, PlainTextDelta}; pub struct ServerFolder { folder_id: String, diff --git a/shared-lib/flowy-sync/src/util.rs b/shared-lib/flowy-sync/src/util.rs index b845550137..92728af8b1 100644 --- a/shared-lib/flowy-sync/src/util.rs +++ b/shared-lib/flowy-sync/src/util.rs @@ -9,7 +9,7 @@ use crate::{ use dissimilar::Chunk; use lib_ot::core::{DeltaBuilder, FlowyStr}; use lib_ot::{ - core::{Attributes, Delta, OperationTransformable, NEW_LINE, WHITESPACE}, + core::{Attributes, Delta, OperationTransform, NEW_LINE, WHITESPACE}, rich_text::RichTextDelta, }; use serde::de::DeserializeOwned; @@ -208,10 +208,10 @@ pub fn cal_diff(old: String, new: String) -> Option> { for chunk in &chunks { match chunk { Chunk::Equal(s) => { - delta_builder = delta_builder.retain(FlowyStr::from(*s).utf16_size()); + delta_builder = delta_builder.retain(FlowyStr::from(*s).utf16_len()); } Chunk::Delete(s) => { - delta_builder = delta_builder.delete(FlowyStr::from(*s).utf16_size()); + delta_builder = delta_builder.delete(FlowyStr::from(*s).utf16_len()); } Chunk::Insert(s) => { delta_builder = delta_builder.insert(*s); diff --git a/shared-lib/lib-ot/src/core/delta/builder.rs b/shared-lib/lib-ot/src/core/delta/builder.rs index 44e4d4dbac..a8bb0459c1 100644 --- a/shared-lib/lib-ot/src/core/delta/builder.rs +++ b/shared-lib/lib-ot/src/core/delta/builder.rs @@ -1,5 +1,6 @@ use crate::core::delta::{trim, Delta}; use crate::core::operation::{Attributes, PhantomAttributes}; +use crate::core::Operation; pub type PlainTextDeltaBuilder = DeltaBuilder; @@ -7,6 +8,16 @@ pub type PlainTextDeltaBuilder = DeltaBuilder; /// /// Note that all edit operations must be sorted; the start point of each /// interval must be no less than the end point of the previous one. +/// +/// # Examples +/// +/// ``` +/// use lib_ot::core::PlainTextDeltaBuilder; +/// let delta = PlainTextDeltaBuilder::new() +/// .insert("AppFlowy") +/// .build(); +/// assert_eq!(delta.content_str().unwrap(), "AppFlowy"); +/// ``` pub struct DeltaBuilder { delta: Delta, } @@ -28,8 +39,26 @@ where DeltaBuilder::default() } + pub fn from_operations(operations: Vec>) -> Delta { + let mut delta = DeltaBuilder::default().build(); + operations.into_iter().for_each(|operation| { + delta.add(operation); + }); + delta + } + /// Retain the 'n' characters with the attributes. Use 'retain' instead if you don't /// need any attributes. + /// # Examples + /// + /// ``` + /// use lib_ot::rich_text::{RichTextAttribute, RichTextDelta, RichTextDeltaBuilder}; + /// + /// let mut attribute = RichTextAttribute::Bold(true); + /// let delta = RichTextDeltaBuilder::new().retain_with_attributes(7, attribute.into()).build(); + /// + /// assert_eq!(delta.to_json_str(), r#"[{"retain":7,"attributes":{"bold":true}}]"#); + /// ``` pub fn retain_with_attributes(mut self, n: usize, attrs: T) -> Self { self.delta.retain(n, attrs); self @@ -41,6 +70,24 @@ where } /// Deletes the given interval. Panics if interval is not properly sorted. + /// + /// # Examples + /// + /// ``` + /// use lib_ot::core::{OperationTransform, PlainTextDeltaBuilder}; + /// + /// let delta = PlainTextDeltaBuilder::new() + /// .insert("AppFlowy...") + /// .build(); + /// + /// let changeset = PlainTextDeltaBuilder::new() + /// .retain(8) + /// .delete(3) + /// .build(); + /// + /// let new_delta = delta.compose(&changeset).unwrap(); + /// assert_eq!(new_delta.content_str().unwrap(), "AppFlowy"); + /// ``` pub fn delete(mut self, n: usize) -> Self { self.delta.delete(n); self @@ -58,6 +105,25 @@ where self } + /// Removes trailing retain operation with empty attributes + /// + /// # Examples + /// + /// ``` + /// use lib_ot::core::{OperationTransform, PlainTextDeltaBuilder}; + /// use lib_ot::rich_text::{RichTextAttribute, RichTextDeltaBuilder}; + /// let delta = PlainTextDeltaBuilder::new() + /// .retain(3) + /// .trim() + /// .build(); + /// assert_eq!(delta.ops.len(), 0); + /// + /// let delta = RichTextDeltaBuilder::new() + /// .retain_with_attributes(3, RichTextAttribute::Bold(true).into()) + /// .trim() + /// .build(); + /// assert_eq!(delta.ops.len(), 1); + /// ``` pub fn trim(mut self) -> Self { trim(&mut self.delta); self diff --git a/shared-lib/lib-ot/src/core/delta/delta.rs b/shared-lib/lib-ot/src/core/delta/delta.rs index 2bff1a3edc..495d26a8e8 100644 --- a/shared-lib/lib-ot/src/core/delta/delta.rs +++ b/shared-lib/lib-ot/src/core/delta/delta.rs @@ -3,7 +3,7 @@ use crate::errors::{ErrorBuilder, OTError, OTErrorCode}; use crate::core::delta::{DeltaIterator, MAX_IV_LEN}; use crate::core::flowy_str::FlowyStr; use crate::core::interval::Interval; -use crate::core::operation::{Attributes, Operation, OperationBuilder, OperationTransformable, PhantomAttributes}; +use crate::core::operation::{Attributes, Operation, OperationBuilder, OperationTransform, PhantomAttributes}; use bytes::Bytes; use serde::de::DeserializeOwned; use std::{ @@ -123,7 +123,7 @@ where return; } - self.utf16_target_len += s.utf16_size(); + self.utf16_target_len += s.utf16_len(); let new_last = match self.ops.as_mut_slice() { [.., Operation::::Insert(insert)] => { // @@ -191,12 +191,12 @@ where /// ``` pub fn apply(&self, applied_str: &str) -> Result { let applied_str: FlowyStr = applied_str.into(); - if applied_str.utf16_size() != self.utf16_base_len { + if applied_str.utf16_len() != self.utf16_base_len { return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength) .msg(format!( "Expected: {}, but received: {}", self.utf16_base_len, - applied_str.utf16_size() + applied_str.utf16_len() )) .build()); } @@ -289,7 +289,7 @@ where } } -impl OperationTransformable for Delta +impl OperationTransform for Delta where T: Attributes, { @@ -568,6 +568,17 @@ impl Delta where T: Attributes + DeserializeOwned, { + /// # Examples + /// + /// ``` + /// use lib_ot::core::DeltaBuilder; + /// use lib_ot::rich_text::{RichTextDelta}; + /// let json = r#"[ + /// {"retain":7,"attributes":{"bold":null}} + /// ]"#; + /// let delta = RichTextDelta::from_json_str(json).unwrap(); + /// assert_eq!(delta.to_json_str(), r#"[{"retain":7,"attributes":{"bold":""}}]"#); + /// ``` pub fn from_json_str(json: &str) -> Result { let delta = serde_json::from_str(json).map_err(|e| { tracing::trace!("Deserialize failed: {:?}", e); diff --git a/shared-lib/lib-ot/src/core/delta/iterator.rs b/shared-lib/lib-ot/src/core/delta/iterator.rs index ba9db58428..d1ab80885f 100644 --- a/shared-lib/lib-ot/src/core/delta/iterator.rs +++ b/shared-lib/lib-ot/src/core/delta/iterator.rs @@ -7,6 +7,18 @@ use std::ops::{Deref, DerefMut}; 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 +/// need any attributes. +/// # Examples +/// +/// ``` +/// use lib_ot::rich_text::{RichTextAttribute, RichTextDelta, RichTextDeltaBuilder}; +/// +/// let mut attribute = RichTextAttribute::Bold(true); +/// let delta = RichTextDeltaBuilder::new().retain_with_attributes(7, attribute.into()).build(); +/// +/// assert_eq!(delta.to_json_str(), r#"[{"retain":7,"attributes":{"bold":true}}]"#); +/// ``` pub struct DeltaIterator<'a, T: Attributes> { cursor: DeltaCursor<'a, T>, } diff --git a/shared-lib/lib-ot/src/core/flowy_str.rs b/shared-lib/lib-ot/src/core/flowy_str.rs index 9e503672eb..2f5ee9b853 100644 --- a/shared-lib/lib-ot/src/core/flowy_str.rs +++ b/shared-lib/lib-ot/src/core/flowy_str.rs @@ -5,8 +5,24 @@ use std::{fmt, fmt::Formatter}; pub struct FlowyStr(pub String); impl FlowyStr { - // https://stackoverflow.com/questions/2241348/what-is-unicode-utf-8-utf-16 - pub fn utf16_size(&self) -> usize { + /// + /// # Arguments + /// + /// * `delta`: The delta you want to iterate over. + /// * `interval`: The range for the cursor movement. + /// + /// # Examples + /// + /// ``` + /// use lib_ot::core::FlowyStr; + /// let utf16_len = FlowyStr::from("πŸ‘‹").utf16_len(); + /// assert_eq!(utf16_len, 2); + /// let bytes_len = String::from("πŸ‘‹").len(); + /// assert_eq!(bytes_len, 4); + /// + /// ``` + /// https://stackoverflow.com/questions/2241348/what-is-unicode-utf-8-utf-16 + pub fn utf16_len(&self) -> usize { count_utf16_code_units(&self.0) } @@ -231,7 +247,7 @@ mod tests { #[test] fn flowy_str_code_unit() { - let size = FlowyStr::from("πŸ‘‹").utf16_size(); + let size = FlowyStr::from("πŸ‘‹").utf16_len(); assert_eq!(size, 2); let s: FlowyStr = "πŸ‘‹ \nπŸ‘‹".into(); @@ -251,7 +267,7 @@ mod tests { #[test] fn flowy_str_sub_str_in_chinese() { let s: FlowyStr = "δ½ ε₯½\n😁".into(); - let size = s.utf16_size(); + let size = s.utf16_len(); assert_eq!(size, 5); let output1 = s.sub_str(Interval::new(0, 2)).unwrap(); @@ -265,7 +281,7 @@ mod tests { #[test] fn flowy_str_sub_str_in_chinese2() { let s: FlowyStr = "😁 \n".into(); - let size = s.utf16_size(); + let size = s.utf16_len(); assert_eq!(size, 4); let output1 = s.sub_str(Interval::new(0, 3)).unwrap(); @@ -277,7 +293,7 @@ mod tests { #[test] fn flowy_str_sub_str_in_english() { let s: FlowyStr = "ab".into(); - let size = s.utf16_size(); + let size = s.utf16_len(); assert_eq!(size, 2); let output = s.sub_str(Interval::new(0, 2)).unwrap(); diff --git a/shared-lib/lib-ot/src/core/operation/builder.rs b/shared-lib/lib-ot/src/core/operation/builder.rs index c2cf774617..d1803a8e21 100644 --- a/shared-lib/lib-ot/src/core/operation/builder.rs +++ b/shared-lib/lib-ot/src/core/operation/builder.rs @@ -5,31 +5,43 @@ pub type RichTextOpBuilder = OperationBuilder; pub type PlainTextOpBuilder = OperationBuilder; pub struct OperationBuilder { - ty: Operation, - attrs: T, + operations: Vec>, } impl OperationBuilder where T: Attributes, { - pub fn new(ty: Operation) -> OperationBuilder { - OperationBuilder { - ty, - attrs: T::default(), + pub fn new() -> OperationBuilder { + OperationBuilder { operations: vec![] } + } + + pub fn retain(mut self, n: usize) -> OperationBuilder { + let mut retain = Operation::Retain(n.into()); + + if let Some(attributes) = attributes { + if let Operation::Retain(r) = &mut retain { + r.attributes = attributes; + } } + self.operations.push(retain); + self } - pub fn retain(n: usize) -> OperationBuilder { - OperationBuilder::new(Operation::Retain(n.into())) + pub fn delete(mut self, n: usize) -> OperationBuilder { + self.operations.push(Operation::Delete(n)); + self } - pub fn delete(n: usize) -> OperationBuilder { - OperationBuilder::new(Operation::Delete(n)) - } - - pub fn insert(s: &str) -> OperationBuilder { - OperationBuilder::new(Operation::Insert(s.into())) + pub fn insert(mut self, s: &str, attributes: Option) -> OperationBuilder { + let mut insert = Operation::Insert(s.into()); + if let Some(attributes) = attributes { + if let Operation::Retain(i) = &mut insert { + i.attributes = attributes; + } + } + self.operations.push(insert); + self } pub fn attributes(mut self, attrs: T) -> OperationBuilder { @@ -37,13 +49,7 @@ where self } - pub fn build(self) -> Operation { - let mut operation = self.ty; - match &mut operation { - Operation::Delete(_) => {} - Operation::Retain(retain) => retain.attributes = self.attrs, - Operation::Insert(insert) => insert.attributes = self.attrs, - } - operation + pub fn build(self) -> Vec> { + self.operations } } diff --git a/shared-lib/lib-ot/src/core/operation/operation.rs b/shared-lib/lib-ot/src/core/operation/operation.rs index 26ac7650ec..9464f91784 100644 --- a/shared-lib/lib-ot/src/core/operation/operation.rs +++ b/shared-lib/lib-ot/src/core/operation/operation.rs @@ -11,7 +11,7 @@ use std::{ ops::{Deref, DerefMut}, }; -pub trait OperationTransformable { +pub trait OperationTransform { /// Merges the operation with `other` into one operation while preserving /// the changes of both. /// @@ -22,7 +22,7 @@ pub trait OperationTransformable { /// # Examples /// /// ``` - /// use lib_ot::core::{OperationTransformable, PlainTextDeltaBuilder}; + /// use lib_ot::core::{OperationTransform, PlainTextDeltaBuilder}; /// let document = PlainTextDeltaBuilder::new().build(); /// let delta = PlainTextDeltaBuilder::new().insert("abc").build(); /// let new_document = document.compose(&delta).unwrap(); @@ -51,7 +51,7 @@ pub trait OperationTransformable { /// # Examples /// /// ``` - /// use lib_ot::core::{OperationTransformable, PlainTextDeltaBuilder}; + /// use lib_ot::core::{OperationTransform, PlainTextDeltaBuilder}; /// let original_document = PlainTextDeltaBuilder::new().build(); /// let delta = PlainTextDeltaBuilder::new().insert("abc").build(); /// @@ -71,7 +71,7 @@ pub trait OperationTransformable { /// Because [Operation] is generic over the T, so you must specify the T. For example, the [PlainTextDelta]. It use /// use [PhantomAttributes] as the T. [PhantomAttributes] does nothing, just a phantom. /// -pub trait Attributes: Default + Display + Eq + PartialEq + Clone + Debug + OperationTransformable { +pub trait Attributes: Default + Display + Eq + PartialEq + Clone + Debug + OperationTransform { fn is_empty(&self) -> bool { true } @@ -360,7 +360,7 @@ where T: Attributes, { pub fn utf16_size(&self) -> usize { - self.s.utf16_size() + self.s.utf16_len() } pub fn merge_or_new_op(&mut self, s: &str, attributes: T) -> Option> { @@ -420,7 +420,7 @@ impl fmt::Display for PhantomAttributes { impl Attributes for PhantomAttributes {} -impl OperationTransformable for PhantomAttributes { +impl OperationTransform for PhantomAttributes { fn compose(&self, _other: &Self) -> Result { Ok(self.clone()) } diff --git a/shared-lib/lib-ot/src/rich_text/attributes.rs b/shared-lib/lib-ot/src/rich_text/attributes.rs index 05d37317d2..54826c49a0 100644 --- a/shared-lib/lib-ot/src/rich_text/attributes.rs +++ b/shared-lib/lib-ot/src/rich_text/attributes.rs @@ -1,5 +1,5 @@ #![allow(non_snake_case)] -use crate::core::{Attributes, Operation, OperationTransformable}; +use crate::core::{Attributes, Operation, OperationTransform}; use crate::{block_attribute, errors::OTError, ignore_attribute, inline_attribute, list_attribute}; use lazy_static::lazy_static; use std::{ @@ -122,7 +122,7 @@ impl Attributes for RichTextAttributes { } } -impl OperationTransformable for RichTextAttributes { +impl OperationTransform for RichTextAttributes { fn compose(&self, other: &Self) -> Result where Self: Sized, From f8c071e13d272d85ecd0f5e9ab3b2d80c96a762a Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 1 Aug 2022 11:18:42 +0800 Subject: [PATCH 2/3] chore: update documentation about how the iterator/FlowyStr/Operation work --- .../flowy-text-block/tests/editor/op_test.rs | 149 +++++++----------- .../tests/editor/serde_test.rs | 6 +- shared-lib/lib-ot/src/core/delta/cursor.rs | 6 +- shared-lib/lib-ot/src/core/delta/delta.rs | 39 ++--- shared-lib/lib-ot/src/core/flowy_str.rs | 62 +++++--- .../lib-ot/src/core/operation/builder.rs | 44 +++--- .../lib-ot/src/core/operation/operation.rs | 96 ++++++++--- 7 files changed, 212 insertions(+), 190 deletions(-) diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs b/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs index 20bb14c063..cb7bb0a728 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs @@ -40,7 +40,7 @@ fn attributes_insert_text_at_middle() { #[test] fn delta_get_ops_in_interval_1() { - let operations = OperationBuilder::new().insert("123", None).insert("4", None).build(); + let operations = OperationsBuilder::new().insert("123").insert("4").build(); let delta = RichTextDeltaBuilder::from_operations(operations); let mut iterator = DeltaIterator::from_interval(&delta, Interval::new(0, 4)); @@ -50,10 +50,10 @@ fn delta_get_ops_in_interval_1() { #[test] fn delta_get_ops_in_interval_2() { let mut delta = RichTextDelta::default(); - let insert_a = OperationBuilder::insert("123").build(); - let insert_b = OperationBuilder::insert("4").build(); - let insert_c = OperationBuilder::insert("5").build(); - let retain_a = OperationBuilder::retain(3).build(); + let insert_a = Operation::insert("123"); + let insert_b = Operation::insert("4"); + let insert_c = Operation::insert("5"); + let retain_a = Operation::retain(3); delta.add(insert_a.clone()); delta.add(retain_a.clone()); @@ -62,12 +62,12 @@ fn delta_get_ops_in_interval_2() { assert_eq!( DeltaIterator::from_interval(&delta, Interval::new(0, 2)).ops(), - vec![OperationBuilder::insert("12").build()] + vec![Operation::insert("12")] ); assert_eq!( DeltaIterator::from_interval(&delta, Interval::new(1, 3)).ops(), - vec![OperationBuilder::insert("23").build()] + vec![Operation::insert("23")] ); assert_eq!( @@ -77,7 +77,7 @@ fn delta_get_ops_in_interval_2() { assert_eq!( DeltaIterator::from_interval(&delta, Interval::new(0, 4)).ops(), - vec![insert_a.clone(), OperationBuilder::retain(1).build()] + vec![insert_a.clone(), Operation::retain(1)] ); assert_eq!( @@ -94,20 +94,20 @@ fn delta_get_ops_in_interval_2() { #[test] fn delta_get_ops_in_interval_3() { let mut delta = RichTextDelta::default(); - let insert_a = OperationBuilder::insert("123456").build(); + let insert_a = Operation::insert("123456"); delta.add(insert_a.clone()); assert_eq!( DeltaIterator::from_interval(&delta, Interval::new(3, 5)).ops(), - vec![OperationBuilder::insert("45").build()] + vec![Operation::insert("45")] ); } #[test] fn delta_get_ops_in_interval_4() { let mut delta = RichTextDelta::default(); - let insert_a = OperationBuilder::insert("12").build(); - let insert_b = OperationBuilder::insert("34").build(); - let insert_c = OperationBuilder::insert("56").build(); + let insert_a = Operation::insert("12"); + let insert_b = Operation::insert("34"); + let insert_c = Operation::insert("56"); delta.ops.push(insert_a.clone()); delta.ops.push(insert_b.clone()); @@ -128,73 +128,64 @@ fn delta_get_ops_in_interval_4() { assert_eq!( DeltaIterator::from_interval(&delta, Interval::new(2, 5)).ops(), - vec![ - OperationBuilder::insert("34").build(), - OperationBuilder::insert("5").build() - ] + vec![Operation::insert("34"), Operation::insert("5")] ); } #[test] fn delta_get_ops_in_interval_5() { let mut delta = RichTextDelta::default(); - let insert_a = OperationBuilder::insert("123456").build(); - let insert_b = OperationBuilder::insert("789").build(); + let insert_a = Operation::insert("123456"); + let insert_b = Operation::insert("789"); delta.ops.push(insert_a.clone()); delta.ops.push(insert_b.clone()); assert_eq!( DeltaIterator::from_interval(&delta, Interval::new(4, 8)).ops(), - vec![ - OperationBuilder::insert("56").build(), - OperationBuilder::insert("78").build() - ] + vec![Operation::insert("56"), Operation::insert("78")] ); // assert_eq!( // DeltaIter::from_interval(&delta, Interval::new(8, 9)).ops(), - // vec![Builder::insert("9").build()] + // vec![Builder::insert("9")] // ); } #[test] fn delta_get_ops_in_interval_6() { let mut delta = RichTextDelta::default(); - let insert_a = OperationBuilder::insert("12345678").build(); + let insert_a = Operation::insert("12345678"); delta.add(insert_a.clone()); assert_eq!( DeltaIterator::from_interval(&delta, Interval::new(4, 6)).ops(), - vec![OperationBuilder::insert("56").build()] + vec![Operation::insert("56")] ); } #[test] fn delta_get_ops_in_interval_7() { let mut delta = RichTextDelta::default(); - let insert_a = OperationBuilder::insert("12345").build(); - let retain_a = OperationBuilder::retain(3).build(); + let insert_a = Operation::insert("12345"); + let retain_a = Operation::retain(3); delta.add(insert_a.clone()); delta.add(retain_a.clone()); let mut iter_1 = DeltaIterator::from_offset(&delta, 2); - assert_eq!(iter_1.next_op().unwrap(), OperationBuilder::insert("345").build()); - assert_eq!(iter_1.next_op().unwrap(), OperationBuilder::retain(3).build()); + assert_eq!(iter_1.next_op().unwrap(), Operation::insert("345")); + assert_eq!(iter_1.next_op().unwrap(), Operation::retain(3)); let mut iter_2 = DeltaIterator::new(&delta); - assert_eq!( - iter_2.next_op_with_len(2).unwrap(), - OperationBuilder::insert("12").build() - ); - assert_eq!(iter_2.next_op().unwrap(), OperationBuilder::insert("345").build()); + assert_eq!(iter_2.next_op_with_len(2).unwrap(), Operation::insert("12")); + assert_eq!(iter_2.next_op().unwrap(), Operation::insert("345")); - assert_eq!(iter_2.next_op().unwrap(), OperationBuilder::retain(3).build()); + assert_eq!(iter_2.next_op().unwrap(), Operation::retain(3)); } #[test] fn delta_op_seek() { let mut delta = RichTextDelta::default(); - let insert_a = OperationBuilder::insert("12345").build(); - let retain_a = OperationBuilder::retain(3).build(); + let insert_a = Operation::insert("12345"); + let retain_a = Operation::retain(3); delta.add(insert_a.clone()); delta.add(retain_a.clone()); let mut iter = DeltaIterator::new(&delta); @@ -205,14 +196,11 @@ fn delta_op_seek() { #[test] fn delta_utf16_code_unit_seek() { let mut delta = RichTextDelta::default(); - delta.add(OperationBuilder::insert("12345").build()); + delta.add(Operation::insert("12345")); let mut iter = DeltaIterator::new(&delta); iter.seek::(3); - assert_eq!( - iter.next_op_with_len(2).unwrap(), - OperationBuilder::insert("45").build() - ); + assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("45")); } #[test] @@ -223,91 +211,76 @@ fn delta_utf16_code_unit_seek_with_attributes() { .add_attr(RichTextAttribute::Italic(true)) .build(); - delta.add(OperationBuilder::insert("1234").attributes(attributes.clone()).build()); - delta.add(OperationBuilder::insert("\n").build()); + delta.add(Operation::insert_with_attributes("1234", attributes.clone())); + delta.add(Operation::insert("\n")); let mut iter = DeltaIterator::new(&delta); iter.seek::(0); assert_eq!( iter.next_op_with_len(4).unwrap(), - OperationBuilder::insert("1234").attributes(attributes).build(), + Operation::insert_with_attributes("1234", attributes), ); } #[test] fn delta_next_op_len() { let mut delta = RichTextDelta::default(); - delta.add(OperationBuilder::insert("12345").build()); + delta.add(Operation::insert("12345")); let mut iter = DeltaIterator::new(&delta); - assert_eq!( - iter.next_op_with_len(2).unwrap(), - OperationBuilder::insert("12").build() - ); - assert_eq!( - iter.next_op_with_len(2).unwrap(), - OperationBuilder::insert("34").build() - ); - assert_eq!(iter.next_op_with_len(2).unwrap(), OperationBuilder::insert("5").build()); + assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("12")); + assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("34")); + assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("5")); assert_eq!(iter.next_op_with_len(1), None); } #[test] fn delta_next_op_len_with_chinese() { let mut delta = RichTextDelta::default(); - delta.add(OperationBuilder::insert("δ½ ε₯½").build()); + delta.add(Operation::insert("δ½ ε₯½")); let mut iter = DeltaIterator::new(&delta); assert_eq!(iter.next_op_len().unwrap(), 2); - assert_eq!( - iter.next_op_with_len(2).unwrap(), - OperationBuilder::insert("δ½ ε₯½").build() - ); + assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("δ½ ε₯½")); } #[test] fn delta_next_op_len_with_english() { let mut delta = RichTextDelta::default(); - delta.add(OperationBuilder::insert("ab").build()); + delta.add(Operation::insert("ab")); let mut iter = DeltaIterator::new(&delta); assert_eq!(iter.next_op_len().unwrap(), 2); - assert_eq!( - iter.next_op_with_len(2).unwrap(), - OperationBuilder::insert("ab").build() - ); + assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("ab")); } #[test] fn delta_next_op_len_after_seek() { let mut delta = RichTextDelta::default(); - delta.add(OperationBuilder::insert("12345").build()); + delta.add(Operation::insert("12345")); let mut iter = DeltaIterator::new(&delta); assert_eq!(iter.next_op_len().unwrap(), 5); iter.seek::(3); assert_eq!(iter.next_op_len().unwrap(), 2); - assert_eq!(iter.next_op_with_len(1).unwrap(), OperationBuilder::insert("4").build()); + assert_eq!(iter.next_op_with_len(1).unwrap(), Operation::insert("4")); assert_eq!(iter.next_op_len().unwrap(), 1); - assert_eq!(iter.next_op().unwrap(), OperationBuilder::insert("5").build()); + assert_eq!(iter.next_op().unwrap(), Operation::insert("5")); } #[test] fn delta_next_op_len_none() { let mut delta = RichTextDelta::default(); - delta.add(OperationBuilder::insert("12345").build()); + delta.add(Operation::insert("12345")); let mut iter = DeltaIterator::new(&delta); assert_eq!(iter.next_op_len().unwrap(), 5); - assert_eq!( - iter.next_op_with_len(5).unwrap(), - OperationBuilder::insert("12345").build() - ); + assert_eq!(iter.next_op_with_len(5).unwrap(), Operation::insert("12345")); assert_eq!(iter.next_op_len(), None); } #[test] fn delta_next_op_with_len_zero() { let mut delta = RichTextDelta::default(); - delta.add(OperationBuilder::insert("12345").build()); + delta.add(Operation::insert("12345")); let mut iter = DeltaIterator::new(&delta); assert_eq!(iter.next_op_with_len(0), None,); assert_eq!(iter.next_op_len().unwrap(), 5); @@ -316,14 +289,14 @@ fn delta_next_op_with_len_zero() { #[test] fn delta_next_op_with_len_cross_op_return_last() { let mut delta = RichTextDelta::default(); - delta.add(OperationBuilder::insert("12345").build()); - delta.add(OperationBuilder::retain(1).build()); - delta.add(OperationBuilder::insert("678").build()); + delta.add(Operation::insert("12345")); + delta.add(Operation::retain(1)); + delta.add(Operation::insert("678")); let mut iter = DeltaIterator::new(&delta); iter.seek::(4); assert_eq!(iter.next_op_len().unwrap(), 1); - assert_eq!(iter.next_op_with_len(2).unwrap(), OperationBuilder::retain(1).build()); + assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::retain(1)); } #[test] @@ -450,22 +423,22 @@ fn ops_merging() { assert_eq!(delta.ops.len(), 0); delta.retain(2, RichTextAttributes::default()); assert_eq!(delta.ops.len(), 1); - assert_eq!(delta.ops.last(), Some(&OperationBuilder::retain(2).build())); + assert_eq!(delta.ops.last(), Some(&Operation::retain(2))); delta.retain(3, RichTextAttributes::default()); assert_eq!(delta.ops.len(), 1); - assert_eq!(delta.ops.last(), Some(&OperationBuilder::retain(5).build())); + assert_eq!(delta.ops.last(), Some(&Operation::retain(5))); delta.insert("abc", RichTextAttributes::default()); assert_eq!(delta.ops.len(), 2); - assert_eq!(delta.ops.last(), Some(&OperationBuilder::insert("abc").build())); + assert_eq!(delta.ops.last(), Some(&Operation::insert("abc"))); delta.insert("xyz", RichTextAttributes::default()); assert_eq!(delta.ops.len(), 2); - assert_eq!(delta.ops.last(), Some(&OperationBuilder::insert("abcxyz").build())); + assert_eq!(delta.ops.last(), Some(&Operation::insert("abcxyz"))); delta.delete(1); assert_eq!(delta.ops.len(), 3); - assert_eq!(delta.ops.last(), Some(&OperationBuilder::delete(1).build())); + assert_eq!(delta.ops.last(), Some(&Operation::delete(1))); delta.delete(1); assert_eq!(delta.ops.len(), 3); - assert_eq!(delta.ops.last(), Some(&OperationBuilder::delete(2).build())); + assert_eq!(delta.ops.last(), Some(&Operation::delete(2))); } #[test] @@ -618,11 +591,11 @@ fn transform_two_conflict_non_seq_delta() { #[test] fn delta_invert_no_attribute_delta() { let mut delta = RichTextDelta::default(); - delta.add(OperationBuilder::insert("123").build()); + delta.add(Operation::insert("123")); let mut change = RichTextDelta::default(); - change.add(OperationBuilder::retain(3).build()); - change.add(OperationBuilder::insert("456").build()); + change.add(Operation::retain(3)); + change.add(Operation::insert("456")); let undo = change.invert(&delta); let new_delta = delta.compose(&change).unwrap(); diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/serde_test.rs b/frontend/rust-lib/flowy-text-block/tests/editor/serde_test.rs index 6c578be6c3..469431c478 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/serde_test.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/serde_test.rs @@ -11,7 +11,7 @@ fn operation_insert_serialize_test() { .add_attr(RichTextAttribute::Bold(true)) .add_attr(RichTextAttribute::Italic(true)) .build(); - let operation = OperationBuilder::insert("123").attributes(attributes).build(); + let operation = Operation::insert_with_attributes("123", attributes); let json = serde_json::to_string(&operation).unwrap(); eprintln!("{}", json); @@ -42,7 +42,7 @@ fn attributes_serialize_test() { .add_attr(RichTextAttribute::Bold(true)) .add_attr(RichTextAttribute::Italic(true)) .build(); - let retain = OperationBuilder::insert("123").attributes(attributes).build(); + let retain = Operation::insert_with_attributes("123", attributes); let json = serde_json::to_string(&retain).unwrap(); eprintln!("{}", json); @@ -56,7 +56,7 @@ fn delta_serialize_multi_attribute_test() { .add_attr(RichTextAttribute::Bold(true)) .add_attr(RichTextAttribute::Italic(true)) .build(); - let retain = OperationBuilder::insert("123").attributes(attributes).build(); + let retain = Operation::insert_with_attributes("123", attributes); delta.add(retain); delta.add(Operation::Retain(5.into())); diff --git a/shared-lib/lib-ot/src/core/delta/cursor.rs b/shared-lib/lib-ot/src/core/delta/cursor.rs index 2243adb7b3..4c223dfd50 100644 --- a/shared-lib/lib-ot/src/core/delta/cursor.rs +++ b/shared-lib/lib-ot/src/core/delta/cursor.rs @@ -29,11 +29,11 @@ where /// # Examples /// /// ``` - /// use lib_ot::core::{DeltaIterator, Interval, OperationBuilder}; + /// use lib_ot::core::{DeltaIterator, Interval, Operation}; /// use lib_ot::rich_text::RichTextDelta; /// let mut delta = RichTextDelta::default(); - /// let op_1 = OperationBuilder::insert("123").build(); - /// let op_2 = OperationBuilder::insert("4").build(); + /// let op_1 = Operation::insert("123"); + /// let op_2 = Operation::insert("4"); /// delta.add(op_1.clone()); /// delta.add(op_2.clone()); /// assert_eq!(DeltaIterator::from_interval(&delta, Interval::new(0, 3)).ops(), vec![op_1.clone()]); diff --git a/shared-lib/lib-ot/src/core/delta/delta.rs b/shared-lib/lib-ot/src/core/delta/delta.rs index 495d26a8e8..53cdcaac54 100644 --- a/shared-lib/lib-ot/src/core/delta/delta.rs +++ b/shared-lib/lib-ot/src/core/delta/delta.rs @@ -3,7 +3,7 @@ use crate::errors::{ErrorBuilder, OTError, OTErrorCode}; use crate::core::delta::{DeltaIterator, MAX_IV_LEN}; use crate::core::flowy_str::FlowyStr; use crate::core::interval::Interval; -use crate::core::operation::{Attributes, Operation, OperationBuilder, OperationTransform, PhantomAttributes}; +use crate::core::operation::{Attributes, Operation, OperationTransform, PhantomAttributes}; use bytes::Bytes; use serde::de::DeserializeOwned; use std::{ @@ -112,7 +112,7 @@ where if let Some(Operation::Delete(n_last)) = self.ops.last_mut() { *n_last += n; } else { - self.ops.push(OperationBuilder::delete(n).build()); + self.ops.push(Operation::delete(n)); } } @@ -135,10 +135,10 @@ where } [.., op_last @ Operation::::Delete(_)] => { let new_last = op_last.clone(); - *op_last = OperationBuilder::::insert(&s).attributes(attributes).build(); + *op_last = Operation::::insert_with_attributes(&s, attributes); Some(new_last) } - _ => Some(OperationBuilder::::insert(&s).attributes(attributes).build()), + _ => Some(Operation::::insert_with_attributes(&s, attributes)), }; match new_last { @@ -160,8 +160,7 @@ where self.ops.push(new_op); } } else { - self.ops - .push(OperationBuilder::::retain(n).attributes(attributes).build()); + self.ops.push(Operation::::retain_with_attributes(n, attributes)); } } @@ -319,10 +318,10 @@ where let op = iter .next_op_with_len(length) - .unwrap_or_else(|| OperationBuilder::retain(length).build()); + .unwrap_or_else(|| Operation::retain(length)); let other_op = other_iter .next_op_with_len(length) - .unwrap_or_else(|| OperationBuilder::retain(length).build()); + .unwrap_or_else(|| Operation::retain(length)); // debug_assert_eq!(op.len(), other_op.len(), "Composing delta failed,"); @@ -330,16 +329,12 @@ where (Operation::Retain(retain), Operation::Retain(other_retain)) => { let composed_attrs = retain.attributes.compose(&other_retain.attributes)?; - new_delta.add(OperationBuilder::retain(retain.n).attributes(composed_attrs).build()) + new_delta.add(Operation::retain_with_attributes(retain.n, composed_attrs)) } (Operation::Insert(insert), Operation::Retain(other_retain)) => { let mut composed_attrs = insert.attributes.compose(&other_retain.attributes)?; composed_attrs.remove_empty(); - new_delta.add( - OperationBuilder::insert(op.get_data()) - .attributes(composed_attrs) - .build(), - ) + new_delta.add(Operation::insert_with_attributes(op.get_data(), composed_attrs)) } (Operation::Retain(_), Operation::Delete(_)) => { new_delta.add(other_op); @@ -402,7 +397,7 @@ where Ordering::Less => { a_prime.retain(retain.n, composed_attrs.clone()); b_prime.retain(retain.n, composed_attrs.clone()); - next_op2 = Some(OperationBuilder::retain(o_retain.n - retain.n).build()); + next_op2 = Some(Operation::retain(o_retain.n - retain.n)); next_op1 = ops1.next(); } Ordering::Equal => { @@ -414,14 +409,14 @@ where Ordering::Greater => { a_prime.retain(o_retain.n, composed_attrs.clone()); b_prime.retain(o_retain.n, composed_attrs.clone()); - next_op1 = Some(OperationBuilder::retain(retain.n - o_retain.n).build()); + next_op1 = Some(Operation::retain(retain.n - o_retain.n)); next_op2 = ops2.next(); } }; } (Some(Operation::Delete(i)), Some(Operation::Delete(j))) => match i.cmp(j) { Ordering::Less => { - next_op2 = Some(OperationBuilder::delete(*j - *i).build()); + next_op2 = Some(Operation::delete(*j - *i)); next_op1 = ops1.next(); } Ordering::Equal => { @@ -429,7 +424,7 @@ where next_op2 = ops2.next(); } Ordering::Greater => { - next_op1 = Some(OperationBuilder::delete(*i - *j).build()); + next_op1 = Some(Operation::delete(*i - *j)); next_op2 = ops2.next(); } }, @@ -437,7 +432,7 @@ where match i.cmp(o_retain) { Ordering::Less => { a_prime.delete(*i); - next_op2 = Some(OperationBuilder::retain(o_retain.n - *i).build()); + next_op2 = Some(Operation::retain(o_retain.n - *i)); next_op1 = ops1.next(); } Ordering::Equal => { @@ -447,7 +442,7 @@ where } Ordering::Greater => { a_prime.delete(o_retain.n); - next_op1 = Some(OperationBuilder::delete(*i - o_retain.n).build()); + next_op1 = Some(Operation::delete(*i - o_retain.n)); next_op2 = ops2.next(); } }; @@ -456,7 +451,7 @@ where match retain.cmp(j) { Ordering::Less => { b_prime.delete(retain.n); - next_op2 = Some(OperationBuilder::delete(*j - retain.n).build()); + next_op2 = Some(Operation::delete(*j - retain.n)); next_op1 = ops1.next(); } Ordering::Equal => { @@ -466,7 +461,7 @@ where } Ordering::Greater => { b_prime.delete(*j); - next_op1 = Some(OperationBuilder::retain(retain.n - *j).build()); + next_op1 = Some(Operation::retain(retain.n - *j)); next_op2 = ops2.next(); } }; diff --git a/shared-lib/lib-ot/src/core/flowy_str.rs b/shared-lib/lib-ot/src/core/flowy_str.rs index 2f5ee9b853..162557f5f3 100644 --- a/shared-lib/lib-ot/src/core/flowy_str.rs +++ b/shared-lib/lib-ot/src/core/flowy_str.rs @@ -30,6 +30,22 @@ impl FlowyStr { Utf16CodeUnitIterator::new(self) } + /// Return a new string with the given [Interval] + /// # Examples + /// + /// ``` + /// use lib_ot::core::{FlowyStr, Interval}; + /// let s: FlowyStr = "δ½ ε₯½\n😁".into(); + /// assert_eq!(s.utf16_len(), 5); + /// let output1 = s.sub_str(Interval::new(0, 2)).unwrap(); + /// assert_eq!(output1, "δ½ ε₯½"); + /// + /// let output2 = s.sub_str(Interval::new(2, 3)).unwrap(); + /// assert_eq!(output2, "\n"); + /// + /// let output3 = s.sub_str(Interval::new(3, 5)).unwrap(); + /// assert_eq!(output3, "😁"); + /// ``` pub fn sub_str(&self, interval: Interval) -> Option { let mut iter = Utf16CodeUnitIterator::new(self); let mut buf = vec![]; @@ -49,8 +65,28 @@ impl FlowyStr { } } + /// Return a new string with the given [Interval] + /// # Examples + /// + /// ``` + /// use lib_ot::core::FlowyStr; + /// let s: FlowyStr = "πŸ‘‹πŸ˜πŸ‘‹".into(); /// + /// let mut iter = s.utf16_code_point_iter(); + /// assert_eq!(iter.next().unwrap(), "πŸ‘‹".to_string()); + /// assert_eq!(iter.next().unwrap(), "😁".to_string()); + /// assert_eq!(iter.next().unwrap(), "πŸ‘‹".to_string()); + /// assert_eq!(iter.next(), None); + /// + /// let s: FlowyStr = "πŸ‘‹12abδΈ€δΊŒπŸ‘‹".into(); /// + /// let mut iter = s.utf16_code_point_iter(); + /// assert_eq!(iter.next().unwrap(), "πŸ‘‹".to_string()); + /// assert_eq!(iter.next().unwrap(), "1".to_string()); + /// assert_eq!(iter.next().unwrap(), "2".to_string()); + /// + /// assert_eq!(iter.skip(FlowyStr::from("abδΈ€δΊŒ").utf16_len()).next().unwrap(), "πŸ‘‹".to_string()); + /// ``` #[allow(dead_code)] - fn utf16_code_point_iter(&self) -> FlowyUtf16CodePointIterator { + pub fn utf16_code_point_iter(&self) -> FlowyUtf16CodePointIterator { FlowyUtf16CodePointIterator::new(self, 0) } } @@ -264,20 +300,6 @@ mod tests { assert_eq!(output, "πŸ‘‹"); } - #[test] - fn flowy_str_sub_str_in_chinese() { - let s: FlowyStr = "δ½ ε₯½\n😁".into(); - let size = s.utf16_len(); - assert_eq!(size, 5); - - let output1 = s.sub_str(Interval::new(0, 2)).unwrap(); - let output2 = s.sub_str(Interval::new(2, 3)).unwrap(); - let output3 = s.sub_str(Interval::new(3, 5)).unwrap(); - assert_eq!(output1, "δ½ ε₯½"); - assert_eq!(output2, "\n"); - assert_eq!(output3, "😁"); - } - #[test] fn flowy_str_sub_str_in_chinese2() { let s: FlowyStr = "😁 \n".into(); @@ -300,16 +322,6 @@ mod tests { assert_eq!(output, "ab"); } - #[test] - fn flowy_str_utf16_code_point_iter_test1() { - let s: FlowyStr = "πŸ‘‹πŸ˜πŸ‘‹".into(); - let mut iter = s.utf16_code_point_iter(); - assert_eq!(iter.next().unwrap(), "πŸ‘‹".to_string()); - assert_eq!(iter.next().unwrap(), "😁".to_string()); - assert_eq!(iter.next().unwrap(), "πŸ‘‹".to_string()); - assert_eq!(iter.next(), None); - } - #[test] fn flowy_str_utf16_code_point_iter_test2() { let s: FlowyStr = "πŸ‘‹πŸ˜πŸ‘‹".into(); diff --git a/shared-lib/lib-ot/src/core/operation/builder.rs b/shared-lib/lib-ot/src/core/operation/builder.rs index d1803a8e21..9483d4cae7 100644 --- a/shared-lib/lib-ot/src/core/operation/builder.rs +++ b/shared-lib/lib-ot/src/core/operation/builder.rs @@ -1,51 +1,47 @@ use crate::core::operation::{Attributes, Operation, PhantomAttributes}; use crate::rich_text::RichTextAttributes; -pub type RichTextOpBuilder = OperationBuilder; -pub type PlainTextOpBuilder = OperationBuilder; +pub type RichTextOpBuilder = OperationsBuilder; +pub type PlainTextOpBuilder = OperationsBuilder; -pub struct OperationBuilder { +pub struct OperationsBuilder { operations: Vec>, } -impl OperationBuilder +impl OperationsBuilder where T: Attributes, { - pub fn new() -> OperationBuilder { - OperationBuilder { operations: vec![] } + pub fn new() -> OperationsBuilder { + OperationsBuilder { operations: vec![] } } - pub fn retain(mut self, n: usize) -> OperationBuilder { - let mut retain = Operation::Retain(n.into()); - - if let Some(attributes) = attributes { - if let Operation::Retain(r) = &mut retain { - r.attributes = attributes; - } - } + pub fn retain_with_attributes(mut self, n: usize, attributes: T) -> OperationsBuilder { + let retain = Operation::retain_with_attributes(n.into(), attributes); self.operations.push(retain); self } - pub fn delete(mut self, n: usize) -> OperationBuilder { + pub fn retain(mut self, n: usize) -> OperationsBuilder { + let retain = Operation::retain(n.into()); + self.operations.push(retain); + self + } + + pub fn delete(mut self, n: usize) -> OperationsBuilder { self.operations.push(Operation::Delete(n)); self } - pub fn insert(mut self, s: &str, attributes: Option) -> OperationBuilder { - let mut insert = Operation::Insert(s.into()); - if let Some(attributes) = attributes { - if let Operation::Retain(i) = &mut insert { - i.attributes = attributes; - } - } + pub fn insert_with_attributes(mut self, s: &str, attributes: T) -> OperationsBuilder { + let insert = Operation::insert_with_attributes(s.into(), attributes); self.operations.push(insert); self } - pub fn attributes(mut self, attrs: T) -> OperationBuilder { - self.attrs = attrs; + pub fn insert(mut self, s: &str) -> OperationsBuilder { + let insert = Operation::insert(s.into()); + self.operations.push(insert); self } diff --git a/shared-lib/lib-ot/src/core/operation/operation.rs b/shared-lib/lib-ot/src/core/operation/operation.rs index 9464f91784..7198c38615 100644 --- a/shared-lib/lib-ot/src/core/operation/operation.rs +++ b/shared-lib/lib-ot/src/core/operation/operation.rs @@ -1,6 +1,5 @@ use crate::core::flowy_str::FlowyStr; use crate::core::interval::Interval; -use crate::core::operation::OperationBuilder; use crate::errors::OTError; use serde::{Deserialize, Serialize, __private::Formatter}; use std::fmt::Display; @@ -105,6 +104,40 @@ impl Operation where T: Attributes, { + pub fn delete(n: usize) -> Self { + Self::Delete(n) + } + + /// Create a [Retain] operation with the given attributes + pub fn retain_with_attributes(n: usize, attributes: T) -> Self { + Self::Retain(Retain { n, attributes }) + } + + /// Create a [Retain] operation without attributes + pub fn retain(n: usize) -> Self { + Self::Retain(Retain { + n, + attributes: T::default(), + }) + } + + /// Create a [Insert] operation with the given attributes + pub fn insert_with_attributes(s: &str, attributes: T) -> Self { + Self::Insert(Insert { + s: FlowyStr::from(s), + attributes, + }) + } + + /// Create a [Insert] operation without attributes + pub fn insert(s: &str) -> Self { + Self::Insert(Insert { + s: FlowyStr::from(s), + attributes: T::default(), + }) + } + + /// Return the String if the operation is [Insert] operation, otherwise return the empty string. pub fn get_data(&self) -> &str { match self { Operation::Delete(_) => "", @@ -152,45 +185,58 @@ where let right; match self { Operation::Delete(n) => { - left = Some(OperationBuilder::::delete(index).build()); - right = Some(OperationBuilder::::delete(*n - index).build()); + left = Some(Operation::::delete(index)); + right = Some(Operation::::delete(*n - index)); } Operation::Retain(retain) => { - left = Some(OperationBuilder::::delete(index).build()); - right = Some(OperationBuilder::::delete(retain.n - index).build()); + left = Some(Operation::::delete(index)); + right = Some(Operation::::delete(retain.n - index)); } Operation::Insert(insert) => { let attributes = self.get_attributes(); - left = Some( - OperationBuilder::::insert(&insert.s[0..index]) - .attributes(attributes.clone()) - .build(), - ); - right = Some( - OperationBuilder::::insert(&insert.s[index..insert.utf16_size()]) - .attributes(attributes) - .build(), - ); + left = Some(Operation::::insert_with_attributes( + &insert.s[0..index], + attributes.clone(), + )); + right = Some(Operation::::insert_with_attributes( + &insert.s[index..insert.utf16_size()], + attributes, + )); } } (left, right) } + /// Returns an operation with the specified width. + /// # Arguments + /// + /// * `interval`: Specify the shrink width of the operation. + /// + /// # Examples + /// + /// ``` + /// use lib_ot::core::{Interval, Operation, PhantomAttributes}; + /// let operation = Operation::::insert("1234"); + /// + /// let op1 = operation.shrink(Interval::new(0,3)).unwrap(); + /// assert_eq!(op1 , Operation::insert("123")); + /// + /// let op2= operation.shrink(Interval::new(3,4)).unwrap(); + /// assert_eq!(op2, Operation::insert("4")); + /// ``` pub fn shrink(&self, interval: Interval) -> Option> { let op = match self { - Operation::Delete(n) => OperationBuilder::delete(min(*n, interval.size())).build(), - Operation::Retain(retain) => OperationBuilder::retain(min(retain.n, interval.size())) - .attributes(retain.attributes.clone()) - .build(), + Operation::Delete(n) => Operation::delete(min(*n, interval.size())), + Operation::Retain(retain) => { + Operation::retain_with_attributes(min(retain.n, interval.size()), retain.attributes.clone()) + } Operation::Insert(insert) => { if interval.start > insert.utf16_size() { - OperationBuilder::insert("").build() + Operation::insert("") } else { let s = insert.s.sub_str(interval).unwrap_or_else(|| "".to_owned()); - OperationBuilder::insert(&s) - .attributes(insert.attributes.clone()) - .build() + Operation::insert_with_attributes(&s, insert.attributes.clone()) } } }; @@ -287,7 +333,7 @@ where self.n += n; None } else { - Some(OperationBuilder::retain(n).attributes(attributes).build()) + Some(Operation::retain_with_attributes(n, attributes)) } } @@ -368,7 +414,7 @@ where self.s += s; None } else { - Some(OperationBuilder::::insert(s).attributes(attributes).build()) + Some(Operation::::insert_with_attributes(s, attributes)) } } From 57a95825d9b5f0f1934146a479f9298c245a29ca Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 1 Aug 2022 11:32:25 +0800 Subject: [PATCH 3/3] chore: rename flowyStr to OTString --- .../tests/editor/attribute_test.rs | 4 +- .../flowy-text-block/tests/editor/mod.rs | 2 +- .../flowy-text-block/tests/editor/op_test.rs | 8 +- shared-lib/flowy-sync/src/util.rs | 6 +- shared-lib/lib-ot/src/core/delta/delta.rs | 12 +-- shared-lib/lib-ot/src/core/flowy_str.rs | 88 +++++++++---------- .../lib-ot/src/core/operation/operation.rs | 12 +-- .../src/core/operation/operation_serde.rs | 6 +- 8 files changed, 69 insertions(+), 69 deletions(-) diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs b/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs index bdeb1601b9..c59d85e025 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs @@ -1,7 +1,7 @@ #![cfg_attr(rustfmt, rustfmt::skip)] use crate::editor::{TestBuilder, TestOp::*}; use flowy_sync::client_document::{NewlineDoc, PlainDoc}; -use lib_ot::core::{Interval, OperationTransform, NEW_LINE, WHITESPACE, FlowyStr}; +use lib_ot::core::{Interval, OperationTransform, NEW_LINE, WHITESPACE, OTString}; use unicode_segmentation::UnicodeSegmentation; use lib_ot::rich_text::RichTextDelta; @@ -723,7 +723,7 @@ fn attributes_preserve_header_format_on_merge() { #[test] fn attributes_format_emoji() { let emoji_s = "πŸ‘‹ "; - let s: FlowyStr = emoji_s.into(); + let s: OTString = emoji_s.into(); let len = s.utf16_len(); assert_eq!(3, len); assert_eq!(2, s.graphemes(true).count()); diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs b/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs index 64f432a1e7..46442a6336 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs @@ -300,7 +300,7 @@ impl Rng { pub fn gen_delta(&mut self, s: &str) -> RichTextDelta { let mut delta = RichTextDelta::default(); - let s = FlowyStr::from(s); + let s = OTString::from(s); loop { let left = s.utf16_len() - delta.utf16_base_len; if left == 0 { diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs b/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs index cb7bb0a728..ac091398b5 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs @@ -333,7 +333,7 @@ fn sequence() { fn apply_1000() { for _ in 0..1 { let mut rng = Rng::default(); - let s: FlowyStr = rng.gen_string(50).into(); + let s: OTString = rng.gen_string(50).into(); let delta = rng.gen_delta(&s); assert_eq!(s.utf16_len(), delta.utf16_base_len); } @@ -458,16 +458,16 @@ fn compose() { let mut rng = Rng::default(); let s = rng.gen_string(20); let a = rng.gen_delta(&s); - let after_a: FlowyStr = a.apply(&s).unwrap().into(); + let after_a: OTString = a.apply(&s).unwrap().into(); assert_eq!(a.utf16_target_len, after_a.utf16_len()); let b = rng.gen_delta(&after_a); - let after_b: FlowyStr = b.apply(&after_a).unwrap().into(); + let after_b: OTString = b.apply(&after_a).unwrap().into(); assert_eq!(b.utf16_target_len, after_b.utf16_len()); let ab = a.compose(&b).unwrap(); assert_eq!(ab.utf16_target_len, b.utf16_target_len); - let after_ab: FlowyStr = ab.apply(&s).unwrap().into(); + let after_ab: OTString = ab.apply(&s).unwrap().into(); assert_eq!(after_b, after_ab); } } diff --git a/shared-lib/flowy-sync/src/util.rs b/shared-lib/flowy-sync/src/util.rs index 92728af8b1..9c0ab822c8 100644 --- a/shared-lib/flowy-sync/src/util.rs +++ b/shared-lib/flowy-sync/src/util.rs @@ -7,7 +7,7 @@ use crate::{ errors::{CollaborateError, CollaborateResult}, }; use dissimilar::Chunk; -use lib_ot::core::{DeltaBuilder, FlowyStr}; +use lib_ot::core::{DeltaBuilder, OTString}; use lib_ot::{ core::{Attributes, Delta, OperationTransform, NEW_LINE, WHITESPACE}, rich_text::RichTextDelta, @@ -208,10 +208,10 @@ pub fn cal_diff(old: String, new: String) -> Option> { for chunk in &chunks { match chunk { Chunk::Equal(s) => { - delta_builder = delta_builder.retain(FlowyStr::from(*s).utf16_len()); + delta_builder = delta_builder.retain(OTString::from(*s).utf16_len()); } Chunk::Delete(s) => { - delta_builder = delta_builder.delete(FlowyStr::from(*s).utf16_len()); + delta_builder = delta_builder.delete(OTString::from(*s).utf16_len()); } Chunk::Insert(s) => { delta_builder = delta_builder.insert(*s); diff --git a/shared-lib/lib-ot/src/core/delta/delta.rs b/shared-lib/lib-ot/src/core/delta/delta.rs index 53cdcaac54..b047091815 100644 --- a/shared-lib/lib-ot/src/core/delta/delta.rs +++ b/shared-lib/lib-ot/src/core/delta/delta.rs @@ -1,7 +1,7 @@ use crate::errors::{ErrorBuilder, OTError, OTErrorCode}; use crate::core::delta::{DeltaIterator, MAX_IV_LEN}; -use crate::core::flowy_str::FlowyStr; +use crate::core::flowy_str::OTString; use crate::core::interval::Interval; use crate::core::operation::{Attributes, Operation, OperationTransform, PhantomAttributes}; use bytes::Bytes; @@ -118,7 +118,7 @@ where /// Creating a [Insert] operation with string, [s]. pub fn insert(&mut self, s: &str, attributes: T) { - let s: FlowyStr = s.into(); + let s: OTString = s.into(); if s.is_empty() { return; } @@ -189,7 +189,7 @@ where /// assert_eq!("hello, AppFlowy", &after_b); /// ``` pub fn apply(&self, applied_str: &str) -> Result { - let applied_str: FlowyStr = applied_str.into(); + let applied_str: OTString = applied_str.into(); if applied_str.utf16_len() != self.utf16_base_len { return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength) .msg(format!( @@ -200,7 +200,7 @@ where .build()); } let mut new_s = String::new(); - let code_point_iter = &mut applied_str.utf16_code_unit_iter(); + let code_point_iter = &mut applied_str.utf16_iter(); for op in &self.ops { match &op { Operation::Retain(retain) => { @@ -246,8 +246,8 @@ where /// pub fn invert_str(&self, inverted_s: &str) -> Self { let mut inverted = Delta::default(); - let inverted_s: FlowyStr = inverted_s.into(); - let code_point_iter = &mut inverted_s.utf16_code_unit_iter(); + let inverted_s: OTString = inverted_s.into(); + let code_point_iter = &mut inverted_s.utf16_iter(); for op in &self.ops { match &op { diff --git a/shared-lib/lib-ot/src/core/flowy_str.rs b/shared-lib/lib-ot/src/core/flowy_str.rs index 162557f5f3..e6811f190c 100644 --- a/shared-lib/lib-ot/src/core/flowy_str.rs +++ b/shared-lib/lib-ot/src/core/flowy_str.rs @@ -1,41 +1,41 @@ use serde::{de, de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; use std::{fmt, fmt::Formatter}; +/// [OTString] uses [String] as its inner container. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct FlowyStr(pub String); +pub struct OTString(pub String); -impl FlowyStr { +impl OTString { + /// Returns the number of UTF-16 code units in this string. /// - /// # Arguments - /// - /// * `delta`: The delta you want to iterate over. - /// * `interval`: The range for the cursor movement. + /// The length of strings behaves differently in different languages. For example: [Dart] string's + /// length is calculated with UTF-16 code units. The method [utf16_len] returns the length of a + /// String in UTF-16 code units. /// /// # Examples /// /// ``` - /// use lib_ot::core::FlowyStr; - /// let utf16_len = FlowyStr::from("πŸ‘‹").utf16_len(); + /// use lib_ot::core::OTString; + /// let utf16_len = OTString::from("πŸ‘‹").utf16_len(); /// assert_eq!(utf16_len, 2); /// let bytes_len = String::from("πŸ‘‹").len(); /// assert_eq!(bytes_len, 4); /// /// ``` - /// https://stackoverflow.com/questions/2241348/what-is-unicode-utf-8-utf-16 pub fn utf16_len(&self) -> usize { count_utf16_code_units(&self.0) } - pub fn utf16_code_unit_iter(&self) -> Utf16CodeUnitIterator { + pub fn utf16_iter(&self) -> Utf16CodeUnitIterator { Utf16CodeUnitIterator::new(self) } - /// Return a new string with the given [Interval] + /// Returns a new string with the given [Interval] /// # Examples /// /// ``` - /// use lib_ot::core::{FlowyStr, Interval}; - /// let s: FlowyStr = "δ½ ε₯½\n😁".into(); + /// use lib_ot::core::{OTString, Interval}; + /// let s: OTString = "δ½ ε₯½\n😁".into(); /// assert_eq!(s.utf16_len(), 5); /// let output1 = s.sub_str(Interval::new(0, 2)).unwrap(); /// assert_eq!(output1, "δ½ ε₯½"); @@ -69,21 +69,21 @@ impl FlowyStr { /// # Examples /// /// ``` - /// use lib_ot::core::FlowyStr; - /// let s: FlowyStr = "πŸ‘‹πŸ˜πŸ‘‹".into(); /// + /// use lib_ot::core::OTString; + /// let s: OTString = "πŸ‘‹πŸ˜πŸ‘‹".into(); /// /// let mut iter = s.utf16_code_point_iter(); /// assert_eq!(iter.next().unwrap(), "πŸ‘‹".to_string()); /// assert_eq!(iter.next().unwrap(), "😁".to_string()); /// assert_eq!(iter.next().unwrap(), "πŸ‘‹".to_string()); /// assert_eq!(iter.next(), None); /// - /// let s: FlowyStr = "πŸ‘‹12abδΈ€δΊŒπŸ‘‹".into(); /// + /// let s: OTString = "πŸ‘‹12abδΈ€δΊŒπŸ‘‹".into(); /// /// let mut iter = s.utf16_code_point_iter(); /// assert_eq!(iter.next().unwrap(), "πŸ‘‹".to_string()); /// assert_eq!(iter.next().unwrap(), "1".to_string()); /// assert_eq!(iter.next().unwrap(), "2".to_string()); /// - /// assert_eq!(iter.skip(FlowyStr::from("abδΈ€δΊŒ").utf16_len()).next().unwrap(), "πŸ‘‹".to_string()); + /// assert_eq!(iter.skip(OTString::from("abδΈ€δΊŒ").utf16_len()).next().unwrap(), "πŸ‘‹".to_string()); /// ``` #[allow(dead_code)] pub fn utf16_code_point_iter(&self) -> FlowyUtf16CodePointIterator { @@ -91,7 +91,7 @@ impl FlowyStr { } } -impl std::ops::Deref for FlowyStr { +impl std::ops::Deref for OTString { type Target = String; fn deref(&self) -> &Self::Target { @@ -99,46 +99,46 @@ impl std::ops::Deref for FlowyStr { } } -impl std::ops::DerefMut for FlowyStr { +impl std::ops::DerefMut for OTString { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl std::convert::From for FlowyStr { +impl std::convert::From for OTString { fn from(s: String) -> Self { - FlowyStr(s) + OTString(s) } } -impl std::convert::From<&str> for FlowyStr { +impl std::convert::From<&str> for OTString { fn from(s: &str) -> Self { s.to_owned().into() } } -impl std::fmt::Display for FlowyStr { +impl std::fmt::Display for OTString { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str(&self.0) } } -impl std::ops::Add<&str> for FlowyStr { - type Output = FlowyStr; +impl std::ops::Add<&str> for OTString { + type Output = OTString; - fn add(self, rhs: &str) -> FlowyStr { + fn add(self, rhs: &str) -> OTString { let new_value = self.0 + rhs; new_value.into() } } -impl std::ops::AddAssign<&str> for FlowyStr { +impl std::ops::AddAssign<&str> for OTString { fn add_assign(&mut self, rhs: &str) { self.0 += rhs; } } -impl Serialize for FlowyStr { +impl Serialize for OTString { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -147,15 +147,15 @@ impl Serialize for FlowyStr { } } -impl<'de> Deserialize<'de> for FlowyStr { - fn deserialize(deserializer: D) -> Result +impl<'de> Deserialize<'de> for OTString { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - struct FlowyStrVisitor; + struct OTStringVisitor; - impl<'de> Visitor<'de> for FlowyStrVisitor { - type Value = FlowyStr; + impl<'de> Visitor<'de> for OTStringVisitor { + type Value = OTString; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a str") @@ -168,19 +168,19 @@ impl<'de> Deserialize<'de> for FlowyStr { Ok(s.into()) } } - deserializer.deserialize_str(FlowyStrVisitor) + deserializer.deserialize_str(OTStringVisitor) } } pub struct Utf16CodeUnitIterator<'a> { - s: &'a FlowyStr, + s: &'a OTString, byte_offset: usize, utf16_offset: usize, utf16_count: usize, } impl<'a> Utf16CodeUnitIterator<'a> { - pub fn new(s: &'a FlowyStr) -> Self { + pub fn new(s: &'a OTString) -> Self { Utf16CodeUnitIterator { s, byte_offset: 0, @@ -219,12 +219,12 @@ impl<'a> Iterator for Utf16CodeUnitIterator<'a> { } pub struct FlowyUtf16CodePointIterator<'a> { - s: &'a FlowyStr, + s: &'a OTString, offset: usize, } impl<'a> FlowyUtf16CodePointIterator<'a> { - pub fn new(s: &'a FlowyStr, offset: usize) -> Self { + pub fn new(s: &'a OTString, offset: usize) -> Self { FlowyUtf16CodePointIterator { s, offset } } } @@ -278,15 +278,15 @@ pub fn len_utf8_from_first_byte(b: u8) -> usize { #[cfg(test)] mod tests { - use crate::core::flowy_str::FlowyStr; + use crate::core::flowy_str::OTString; use crate::core::interval::Interval; #[test] fn flowy_str_code_unit() { - let size = FlowyStr::from("πŸ‘‹").utf16_len(); + let size = OTString::from("πŸ‘‹").utf16_len(); assert_eq!(size, 2); - let s: FlowyStr = "πŸ‘‹ \nπŸ‘‹".into(); + let s: OTString = "πŸ‘‹ \nπŸ‘‹".into(); let output = s.sub_str(Interval::new(0, size)).unwrap(); assert_eq!(output, "πŸ‘‹"); @@ -302,7 +302,7 @@ mod tests { #[test] fn flowy_str_sub_str_in_chinese2() { - let s: FlowyStr = "😁 \n".into(); + let s: OTString = "😁 \n".into(); let size = s.utf16_len(); assert_eq!(size, 4); @@ -314,7 +314,7 @@ mod tests { #[test] fn flowy_str_sub_str_in_english() { - let s: FlowyStr = "ab".into(); + let s: OTString = "ab".into(); let size = s.utf16_len(); assert_eq!(size, 2); @@ -324,7 +324,7 @@ mod tests { #[test] fn flowy_str_utf16_code_point_iter_test2() { - let s: FlowyStr = "πŸ‘‹πŸ˜πŸ‘‹".into(); + let s: OTString = "πŸ‘‹πŸ˜πŸ‘‹".into(); let iter = s.utf16_code_point_iter(); let result = iter.skip(1).take(1).collect::(); assert_eq!(result, "😁".to_string()); diff --git a/shared-lib/lib-ot/src/core/operation/operation.rs b/shared-lib/lib-ot/src/core/operation/operation.rs index 7198c38615..482a5739ad 100644 --- a/shared-lib/lib-ot/src/core/operation/operation.rs +++ b/shared-lib/lib-ot/src/core/operation/operation.rs @@ -1,4 +1,4 @@ -use crate::core::flowy_str::FlowyStr; +use crate::core::flowy_str::OTString; use crate::core::interval::Interval; use crate::errors::OTError; use serde::{Deserialize, Serialize, __private::Formatter}; @@ -124,7 +124,7 @@ where /// Create a [Insert] operation with the given attributes pub fn insert_with_attributes(s: &str, attributes: T) -> Self { Self::Insert(Insert { - s: FlowyStr::from(s), + s: OTString::from(s), attributes, }) } @@ -132,7 +132,7 @@ where /// Create a [Insert] operation without attributes pub fn insert(s: &str) -> Self { Self::Insert(Insert { - s: FlowyStr::from(s), + s: OTString::from(s), attributes: T::default(), }) } @@ -376,7 +376,7 @@ where #[derive(Clone, Debug, Eq, PartialEq)] pub struct Insert { - pub s: FlowyStr, + pub s: OTString, pub attributes: T, } @@ -444,11 +444,11 @@ where } } -impl std::convert::From for Insert +impl std::convert::From for Insert where T: Attributes, { - fn from(s: FlowyStr) -> Self { + fn from(s: OTString) -> Self { Insert { s, attributes: T::default(), diff --git a/shared-lib/lib-ot/src/core/operation/operation_serde.rs b/shared-lib/lib-ot/src/core/operation/operation_serde.rs index d029fb0e16..40386235da 100644 --- a/shared-lib/lib-ot/src/core/operation/operation_serde.rs +++ b/shared-lib/lib-ot/src/core/operation/operation_serde.rs @@ -1,4 +1,4 @@ -use crate::core::flowy_str::FlowyStr; +use crate::core::flowy_str::OTString; use crate::core::operation::{Attributes, Insert, Operation, Retain}; use serde::{ de, @@ -249,7 +249,7 @@ where where A: SeqAccess<'de>, { - let s = match serde::de::SeqAccess::next_element::(&mut seq)? { + let s = match serde::de::SeqAccess::next_element::(&mut seq)? { Some(val) => val, None => { return Err(de::Error::invalid_length(0, &"struct Insert with 2 elements")); @@ -271,7 +271,7 @@ where where V: MapAccess<'de>, { - let mut s: Option = None; + let mut s: Option = None; let mut attributes: Option = None; while let Some(key) = map.next_key()? { match key {