diff --git a/rust-lib/flowy-ot/src/client/document.rs b/rust-lib/flowy-ot/src/client/document.rs index 0d2918ef15..62328914d4 100644 --- a/rust-lib/flowy-ot/src/client/document.rs +++ b/rust-lib/flowy-ot/src/client/document.rs @@ -1,5 +1,5 @@ use crate::{ - client::{History, RevId, UndoResult}, + client::{view::View, History, RevId, UndoResult}, core::*, errors::{ErrorBuilder, OTError, OTErrorCode::*}, }; @@ -7,8 +7,9 @@ use crate::{ pub const RECORD_THRESHOLD: usize = 400; // in milliseconds pub struct Document { - data: Delta, + delta: Delta, history: History, + view: View, rev_id_counter: usize, last_edit_time: usize, } @@ -17,26 +18,30 @@ impl Document { pub fn new() -> Self { let delta = Delta::new(); Document { - data: delta, + delta, history: History::new(), + view: View::new(), rev_id_counter: 1, last_edit_time: 0, } } pub fn insert(&mut self, index: usize, text: &str) -> Result<(), OTError> { - if self.data.target_len < index { + if self.delta.target_len < index { log::error!( "{} out of bounds. should 0..{}", index, - self.data.target_len + self.delta.target_len ); } let probe = Interval::new(index, index + 1); - let mut attributes = self.data.get_attributes(probe); + let mut attributes = self.delta.get_attributes(probe); if attributes.is_empty() { attributes = Attributes::Follow; } + + // let delta = self.view.handle_insert(&self.delta, s, interval); + let mut delta = Delta::new(); let insert = Builder::insert(text).attributes(attributes).build(); let interval = Interval::new(index, index); @@ -86,7 +91,7 @@ impl Document { Some(undo_delta) => { let (new_delta, inverted_delta) = self.invert_change(&undo_delta)?; let result = UndoResult::success(new_delta.target_len as usize); - self.data = new_delta; + self.delta = new_delta; self.history.add_redo(inverted_delta); Ok(result) @@ -100,7 +105,7 @@ impl Document { Some(redo_delta) => { let (new_delta, inverted_delta) = self.invert_change(&redo_delta)?; let result = UndoResult::success(new_delta.target_len as usize); - self.data = new_delta; + self.delta = new_delta; self.history.add_undo(inverted_delta); Ok(result) @@ -108,26 +113,27 @@ impl Document { } } - pub fn to_json(&self) -> String { self.data.to_json() } + pub fn to_json(&self) -> String { self.delta.to_json() } - pub fn to_string(&self) -> String { self.data.apply("").unwrap() } + pub fn to_string(&self) -> String { self.delta.apply("").unwrap() } - pub fn data(&self) -> &Delta { &self.data } + pub fn data(&self) -> &Delta { &self.delta } - pub fn set_data(&mut self, data: Delta) { self.data = data; } + pub fn set_data(&mut self, data: Delta) { self.delta = data; } fn update_with_op(&mut self, delta: &Delta, interval: Interval) -> Result<(), OTError> { let mut new_delta = Delta::default(); - let (prefix, interval, suffix) = split_length_with_interval(self.data.target_len, interval); + let (prefix, interval, suffix) = + split_length_with_interval(self.delta.target_len, interval); // prefix if prefix.is_empty() == false && prefix != interval { - let intervals = split_interval_with_delta(&self.data, &prefix); - intervals.into_iter().for_each(|i| { - let attributes = self.data.get_attributes(i); - log::trace!("prefix attribute: {:?}, interval: {:?}", attributes, i); - new_delta.retain(i.size() as usize, attributes); - }); + DeltaAttributesIter::from_interval(&self.delta, prefix).for_each( + |(length, attributes)| { + log::debug!("prefix attribute: {:?}, len: {}", attributes, length); + new_delta.retain(length, attributes); + }, + ); } delta.ops.iter().for_each(|op| { @@ -136,15 +142,15 @@ impl Document { // suffix if suffix.is_empty() == false { - let intervals = split_interval_with_delta(&self.data, &suffix); - intervals.into_iter().for_each(|i| { - let attributes = self.data.get_attributes(i); - log::trace!("suffix attribute: {:?}, interval: {:?}", attributes, i); - new_delta.retain(i.size() as usize, attributes); - }); + DeltaAttributesIter::from_interval(&self.delta, suffix).for_each( + |(length, attributes)| { + log::debug!("suffix attribute: {:?}, len: {}", attributes, length); + new_delta.retain(length, attributes); + }, + ); } - self.data = self.record_change(&new_delta)?; + self.delta = self.record_change(&new_delta)?; Ok(()) } @@ -154,7 +160,7 @@ impl Document { interval: Interval, ) -> Result<(), OTError> { log::debug!("Update document with attributes: {:?}", attributes,); - let old_attributes = self.data.get_attributes(interval); + let old_attributes = self.delta.get_attributes(interval); log::debug!("combine with old: {:?}", old_attributes); let new_attributes = match &mut attributes { Attributes::Follow => old_attributes, @@ -208,8 +214,8 @@ impl Document { // d = b.invert(a) // a = c.compose(d) log::debug!("👉invert change {}", change); - let new_delta = self.data.compose(change)?; - let inverted_delta = change.invert(&self.data); + let new_delta = self.delta.compose(change)?; + let inverted_delta = change.invert(&self.delta); // trim(&mut inverted_delta); Ok((new_delta, inverted_delta)) @@ -223,7 +229,7 @@ fn split_length_with_interval(length: usize, interval: Interval) -> (Interval, I (prefix, interval, suffix) } -fn split_interval_with_delta(delta: &Delta, interval: &Interval) -> Vec { +fn split_interval_by_delta(delta: &Delta, interval: &Interval) -> Vec { let mut start = 0; let mut new_intervals = vec![]; delta.ops.iter().for_each(|op| match op { diff --git a/rust-lib/flowy-ot/src/client/view/extension.rs b/rust-lib/flowy-ot/src/client/view/extension.rs index 52ee4ac521..cbe3b62398 100644 --- a/rust-lib/flowy-ot/src/client/view/extension.rs +++ b/rust-lib/flowy-ot/src/client/view/extension.rs @@ -1,23 +1,17 @@ use crate::{ client::{view::insert_ext::*, Document}, - core::{Attributes, Interval}, + core::{Attributes, Delta, Interval}, }; use lazy_static::lazy_static; pub trait InsertExt { - fn apply(document: &Document, s: &str, interval: Interval); + fn apply(&self, delta: &Delta, s: &str, interval: Interval) -> Delta; } pub trait FormatExt { - fn apply(document: &Document, interval: Interval, attributes: Attributes); + fn apply(&self, document: &Document, interval: Interval, attributes: Attributes); } pub trait DeleteExt { - fn apply(document: &Document, interval: Interval); -} - -lazy_static! { - static ref INSERT_EXT: Vec> = vec![PreserveInlineStyleExt::new(),]; - static ref FORMAT_EXT: Vec> = vec![]; - static ref DELETE_EXT: Vec> = vec![]; + fn apply(&self, document: &Document, interval: Interval); } diff --git a/rust-lib/flowy-ot/src/client/view/insert_ext.rs b/rust-lib/flowy-ot/src/client/view/insert_ext.rs index 3904e0f541..a16b895f38 100644 --- a/rust-lib/flowy-ot/src/client/view/insert_ext.rs +++ b/rust-lib/flowy-ot/src/client/view/insert_ext.rs @@ -1,14 +1,22 @@ use crate::{ client::{view::InsertExt, Document}, - core::Interval, + core::{Builder, Delta, Interval}, }; pub struct PreserveInlineStyleExt {} impl PreserveInlineStyleExt { - pub fn new() -> Self {} + pub fn new() -> Self { Self {} } } impl InsertExt for PreserveInlineStyleExt { - fn apply(document: &Document, s: &str, interval: Interval) { unimplemented!() } + fn apply(&self, delta: &Delta, s: &str, interval: Interval) -> Delta { + // let mut delta = Delta::default(); + // let insert = Builder::insert(text).attributes(attributes).build(); + // let interval = Interval::new(index, index); + // delta.add(insert); + // + // delta + unimplemented!() + } } diff --git a/rust-lib/flowy-ot/src/client/view/mod.rs b/rust-lib/flowy-ot/src/client/view/mod.rs index 835ea3edc4..6a5a4b14d0 100644 --- a/rust-lib/flowy-ot/src/client/view/mod.rs +++ b/rust-lib/flowy-ot/src/client/view/mod.rs @@ -1,6 +1,7 @@ mod extension; mod insert_ext; +mod view; pub use extension::*; - pub use insert_ext::*; +pub use view::*; diff --git a/rust-lib/flowy-ot/src/client/view/view.rs b/rust-lib/flowy-ot/src/client/view/view.rs new file mode 100644 index 0000000000..f1ab67c0f4 --- /dev/null +++ b/rust-lib/flowy-ot/src/client/view/view.rs @@ -0,0 +1,32 @@ +use crate::{ + client::view::{InsertExt, PreserveInlineStyleExt}, + core::{Delta, Interval}, +}; + +type InsertExtension = Box; + +pub struct View { + insert_exts: Vec, +} + +impl View { + pub(crate) fn new() -> Self { + let insert_exts = construct_insert_exts(); + Self { insert_exts } + } + + pub(crate) fn handle_insert(&self, delta: &Delta, s: &str, interval: Interval) -> Delta { + let mut new_delta = Delta::new(); + self.insert_exts.iter().for_each(|ext| { + new_delta = ext.apply(delta, s, interval); + }); + new_delta + } +} + +fn construct_insert_exts() -> Vec { + vec![ + // + Box::new(PreserveInlineStyleExt::new()), + ] +} diff --git a/rust-lib/flowy-ot/src/core/delta/cursor.rs b/rust-lib/flowy-ot/src/core/delta/cursor.rs index 04abe86186..dbe457bb6f 100644 --- a/rust-lib/flowy-ot/src/core/delta/cursor.rs +++ b/rust-lib/flowy-ot/src/core/delta/cursor.rs @@ -1,4 +1,4 @@ -use crate::core::{Delta, Interval, Operation}; +use crate::core::{Attributes, AttributesData, Delta, Interval, Operation}; use std::{cmp::min, slice::Iter}; pub struct Cursor<'a> { @@ -77,7 +77,12 @@ pub struct DeltaIter<'a> { } impl<'a> DeltaIter<'a> { - pub fn new(delta: &'a Delta, interval: Interval) -> Self { + pub fn new(delta: &'a Delta) -> Self { + let interval = Interval::new(0, usize::MAX); + Self::from_interval(delta, interval) + } + + pub fn from_interval(delta: &'a Delta, interval: Interval) -> Self { let cursor = Cursor::new(delta, interval); Self { cursor, interval } } @@ -87,9 +92,62 @@ impl<'a> DeltaIter<'a> { impl<'a> Iterator for DeltaIter<'a> { type Item = Operation; - fn next(&mut self) -> Option { self.cursor.next_op() } } + +pub struct DeltaAttributesIter<'a> { + delta_iter: DeltaIter<'a>, + interval: Interval, +} + +impl<'a> DeltaAttributesIter<'a> { + pub fn new(delta: &'a Delta) -> Self { + let interval = Interval::new(0, usize::MAX); + Self::from_interval(delta, interval) + } + + pub fn from_interval(delta: &'a Delta, interval: Interval) -> Self { + let delta_iter = DeltaIter::from_interval(delta, interval); + Self { + delta_iter, + interval, + } + } +} + +impl<'a> Iterator for DeltaAttributesIter<'a> { + type Item = (usize, Attributes); + fn next(&mut self) -> Option { + let next_op = self.delta_iter.next(); + if next_op.is_none() { + return None; + } + let mut length: usize = 0; + let mut attributes_data = AttributesData::new(); + + match next_op.unwrap() { + Operation::Delete(_n) => {}, + Operation::Retain(retain) => { + if let Attributes::Custom(data) = &retain.attributes { + log::debug!("extend retain attributes with {} ", &data); + attributes_data.extend(Some(data.clone())); + } + length = retain.n; + }, + Operation::Insert(insert) => { + if let Attributes::Custom(data) = &insert.attributes { + log::debug!("extend insert attributes with {} ", &data); + attributes_data.extend(Some(data.clone())); + } + length = insert.num_chars(); + }, + } + + let attribute: Attributes = attributes_data.into(); + Some((length, attribute)) + } +} + #[cfg(test)] mod tests { diff --git a/rust-lib/flowy-ot/src/core/delta/delta.rs b/rust-lib/flowy-ot/src/core/delta/delta.rs index 7ab1a59ecd..bc3671e9bc 100644 --- a/rust-lib/flowy-ot/src/core/delta/delta.rs +++ b/rust-lib/flowy-ot/src/core/delta/delta.rs @@ -573,7 +573,7 @@ fn invert_from_other( end: usize, ) { log::debug!("invert op: {} [{}:{}]", operation, start, end); - let other_ops = DeltaIter::new(other, Interval::new(start, end)).ops(); + let other_ops = DeltaIter::from_interval(other, Interval::new(start, end)).ops(); other_ops.into_iter().for_each(|other_op| match operation { Operation::Delete(n) => { log::debug!("invert delete: {} by add {}", n, other_op); diff --git a/rust-lib/flowy-ot/tests/helper/mod.rs b/rust-lib/flowy-ot/tests/helper/mod.rs index f804c3b5e5..e6a847df68 100644 --- a/rust-lib/flowy-ot/tests/helper/mod.rs +++ b/rust-lib/flowy-ot/tests/helper/mod.rs @@ -57,7 +57,7 @@ impl OpTester { static INIT: Once = Once::new(); INIT.call_once(|| { color_eyre::install().unwrap(); - std::env::set_var("RUST_LOG", "info"); + std::env::set_var("RUST_LOG", "debug"); env_logger::init(); }); diff --git a/rust-lib/flowy-ot/tests/op_test.rs b/rust-lib/flowy-ot/tests/op_test.rs index b4210fc691..50d25bd741 100644 --- a/rust-lib/flowy-ot/tests/op_test.rs +++ b/rust-lib/flowy-ot/tests/op_test.rs @@ -14,7 +14,7 @@ fn delta_get_ops_in_interval_1() { delta.add(insert_a.clone()); delta.add(insert_b.clone()); - let mut iterator = DeltaIter::new(&delta, Interval::new(0, 4)); + let mut iterator = DeltaIter::from_interval(&delta, Interval::new(0, 4)); assert_eq!(iterator.ops(), delta.ops); } @@ -32,27 +32,27 @@ fn delta_get_ops_in_interval_2() { delta.add(insert_c.clone()); assert_eq!( - DeltaIter::new(&delta, Interval::new(0, 2)).ops(), + DeltaIter::from_interval(&delta, Interval::new(0, 2)).ops(), vec![Builder::insert("12").build()] ); assert_eq!( - DeltaIter::new(&delta, Interval::new(0, 3)).ops(), + DeltaIter::from_interval(&delta, Interval::new(0, 3)).ops(), vec![insert_a.clone()] ); assert_eq!( - DeltaIter::new(&delta, Interval::new(0, 4)).ops(), + DeltaIter::from_interval(&delta, Interval::new(0, 4)).ops(), vec![insert_a.clone(), Builder::retain(1).build()] ); assert_eq!( - DeltaIter::new(&delta, Interval::new(0, 6)).ops(), + DeltaIter::from_interval(&delta, Interval::new(0, 6)).ops(), vec![insert_a.clone(), retain_a.clone()] ); assert_eq!( - DeltaIter::new(&delta, Interval::new(0, 7)).ops(), + DeltaIter::from_interval(&delta, Interval::new(0, 7)).ops(), vec![insert_a.clone(), retain_a.clone(), insert_b.clone()] ); } @@ -63,7 +63,7 @@ fn delta_get_ops_in_interval_3() { let insert_a = Builder::insert("123456").build(); delta.add(insert_a.clone()); assert_eq!( - DeltaIter::new(&delta, Interval::new(3, 5)).ops(), + DeltaIter::from_interval(&delta, Interval::new(3, 5)).ops(), vec![Builder::insert("45").build()] ); } @@ -80,20 +80,20 @@ fn delta_get_ops_in_interval_4() { delta.ops.push(insert_c.clone()); assert_eq!( - DeltaIter::new(&delta, Interval::new(0, 2)).ops(), + DeltaIter::from_interval(&delta, Interval::new(0, 2)).ops(), vec![insert_a] ); assert_eq!( - DeltaIter::new(&delta, Interval::new(2, 4)).ops(), + DeltaIter::from_interval(&delta, Interval::new(2, 4)).ops(), vec![insert_b] ); assert_eq!( - DeltaIter::new(&delta, Interval::new(4, 6)).ops(), + DeltaIter::from_interval(&delta, Interval::new(4, 6)).ops(), vec![insert_c] ); assert_eq!( - DeltaIter::new(&delta, Interval::new(2, 5)).ops(), + DeltaIter::from_interval(&delta, Interval::new(2, 5)).ops(), vec![Builder::insert("34").build(), Builder::insert("5").build()] ); } @@ -106,12 +106,12 @@ fn delta_get_ops_in_interval_5() { delta.ops.push(insert_a.clone()); delta.ops.push(insert_b.clone()); assert_eq!( - DeltaIter::new(&delta, Interval::new(4, 8)).ops(), + DeltaIter::from_interval(&delta, Interval::new(4, 8)).ops(), vec![Builder::insert("56").build(), Builder::insert("78").build()] ); assert_eq!( - DeltaIter::new(&delta, Interval::new(8, 9)).ops(), + DeltaIter::from_interval(&delta, Interval::new(8, 9)).ops(), vec![Builder::insert("9").build()] ); } @@ -122,7 +122,7 @@ fn delta_get_ops_in_interval_6() { let insert_a = Builder::insert("12345678").build(); delta.add(insert_a.clone()); assert_eq!( - DeltaIter::new(&delta, Interval::new(4, 6)).ops(), + DeltaIter::from_interval(&delta, Interval::new(4, 6)).ops(), vec![Builder::insert("56").build()] ); }