瀏覽代碼

add attribute iterator

appflowy 3 年之前
父節點
當前提交
039b4917ed

+ 36 - 30
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<Interval> {
+fn split_interval_by_delta(delta: &Delta, interval: &Interval) -> Vec<Interval> {
     let mut start = 0;
     let mut new_intervals = vec![];
     delta.ops.iter().for_each(|op| match op {

+ 4 - 10
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<Box<InsertExt>> = vec![PreserveInlineStyleExt::new(),];
-    static ref FORMAT_EXT: Vec<Box<FormatExt>> = vec![];
-    static ref DELETE_EXT: Vec<Box<DeleteExt>> = vec![];
+    fn apply(&self, document: &Document, interval: Interval);
 }

+ 11 - 3
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!()
+    }
 }

+ 2 - 1
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::*;

+ 32 - 0
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<dyn InsertExt>;
+
+pub struct View {
+    insert_exts: Vec<InsertExtension>,
+}
+
+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<InsertExtension> {
+    vec![
+        //
+        Box::new(PreserveInlineStyleExt::new()),
+    ]
+}

+ 61 - 3
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::Item> { 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<Self::Item> {
+        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 {
 

+ 1 - 1
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);

+ 1 - 1
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();
         });
 

+ 14 - 14
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()]
     );
 }