소스 검색

splite attribute and operation into crate

appflowy 3 년 전
부모
커밋
97bba6e286

+ 5 - 0
rust-lib/flowy-ot/src/client/mod.rs

@@ -0,0 +1,5 @@
+mod document;
+mod history;
+
+pub use document::*;
+pub use history::*;

+ 0 - 295
rust-lib/flowy-ot/src/core/attributes.rs

@@ -1,295 +0,0 @@
-use crate::core::Operation;
-use std::{collections::HashMap, fmt};
-
-const REMOVE_FLAG: &'static str = "";
-fn should_remove(s: &str) -> bool { s == REMOVE_FLAG }
-
-#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
-#[serde(untagged)]
-pub enum Attributes {
-    #[serde(skip)]
-    Follow,
-    Custom(AttributesData),
-    #[serde(skip)]
-    Empty,
-}
-
-impl Attributes {
-    pub fn data(&self) -> Option<AttributesData> {
-        match self {
-            Attributes::Follow => None,
-            Attributes::Custom(data) => Some(data.clone()),
-            Attributes::Empty => None,
-        }
-    }
-
-    pub fn is_empty(&self) -> bool {
-        match self {
-            Attributes::Follow => true,
-            Attributes::Custom(data) => data.is_empty(),
-            Attributes::Empty => true,
-        }
-    }
-}
-
-impl std::default::Default for Attributes {
-    fn default() -> Self { Attributes::Empty }
-}
-
-impl fmt::Display for Attributes {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Attributes::Follow => {
-                f.write_str("")?;
-            },
-            Attributes::Custom(data) => {
-                f.write_fmt(format_args!("{:?}", data.inner))?;
-            },
-            Attributes::Empty => {
-                f.write_str("")?;
-            },
-        }
-        Ok(())
-    }
-}
-
-#[derive(Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)]
-pub struct AttributesData {
-    #[serde(skip_serializing_if = "HashMap::is_empty")]
-    #[serde(flatten)]
-    inner: HashMap<String, String>,
-}
-
-impl AttributesData {
-    pub fn new() -> Self {
-        AttributesData {
-            inner: HashMap::new(),
-        }
-    }
-    pub fn is_empty(&self) -> bool {
-        self.inner.values().filter(|v| !should_remove(v)).count() == 0
-    }
-
-    fn remove_empty(&mut self) { self.inner.retain(|_, v| !should_remove(v)); }
-
-    pub fn extend(&mut self, other: AttributesData) { self.inner.extend(other.inner); }
-
-    pub fn merge(&mut self, other: Option<AttributesData>) {
-        if other.is_none() {
-            return;
-        }
-
-        let mut new_attributes = other.unwrap().inner;
-        self.inner.iter().for_each(|(k, v)| {
-            if should_remove(v) {
-                new_attributes.remove(k);
-            } else {
-                new_attributes.insert(k.clone(), v.clone());
-            }
-        });
-        self.inner = new_attributes;
-    }
-}
-
-pub trait AttributesDataRule {
-    fn apply_rule(&mut self);
-
-    fn into_attributes(self) -> Attributes;
-}
-impl AttributesDataRule for AttributesData {
-    fn apply_rule(&mut self) { self.remove_empty(); }
-
-    fn into_attributes(mut self) -> Attributes {
-        self.apply_rule();
-
-        if self.is_empty() {
-            Attributes::Empty
-        } else {
-            Attributes::Custom(self)
-        }
-    }
-}
-
-pub trait AttributesRule {
-    fn apply_rule(self) -> Attributes;
-}
-
-impl AttributesRule for Attributes {
-    fn apply_rule(self) -> Attributes {
-        match self {
-            Attributes::Follow => self,
-            Attributes::Custom(data) => data.into_attributes(),
-            Attributes::Empty => self,
-        }
-    }
-}
-
-impl std::convert::From<HashMap<String, String>> for AttributesData {
-    fn from(attributes: HashMap<String, String>) -> Self { AttributesData { inner: attributes } }
-}
-
-impl std::ops::Deref for AttributesData {
-    type Target = HashMap<String, String>;
-
-    fn deref(&self) -> &Self::Target { &self.inner }
-}
-
-impl std::ops::DerefMut for AttributesData {
-    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner }
-}
-
-pub struct AttrsBuilder {
-    inner: AttributesData,
-}
-
-impl AttrsBuilder {
-    pub fn new() -> Self {
-        Self {
-            inner: AttributesData::default(),
-        }
-    }
-
-    pub fn bold(mut self, bold: bool) -> Self {
-        let val = match bold {
-            true => "true",
-            false => REMOVE_FLAG,
-        };
-        self.inner.insert("bold".to_owned(), val.to_owned());
-        self
-    }
-
-    pub fn italic(mut self, italic: bool) -> Self {
-        let val = match italic {
-            true => "true",
-            false => REMOVE_FLAG,
-        };
-        self.inner.insert("italic".to_owned(), val.to_owned());
-        self
-    }
-
-    pub fn underline(mut self) -> Self {
-        self.inner.insert("underline".to_owned(), "true".to_owned());
-        self
-    }
-
-    pub fn build(self) -> Attributes { Attributes::Custom(self.inner) }
-}
-
-pub(crate) fn attributes_from(operation: &Option<Operation>) -> Option<Attributes> {
-    match operation {
-        None => None,
-        Some(operation) => Some(operation.get_attributes()),
-    }
-}
-
-pub fn compose_operation(left: &Option<Operation>, right: &Option<Operation>) -> Attributes {
-    if left.is_none() && right.is_none() {
-        return Attributes::Empty;
-    }
-    let attr_l = attributes_from(left);
-    let attr_r = attributes_from(right);
-
-    if attr_l.is_none() {
-        return attr_r.unwrap();
-    }
-
-    if attr_r.is_none() {
-        return attr_l.unwrap();
-    }
-
-    compose_attributes(attr_l.unwrap(), attr_r.unwrap())
-}
-
-pub fn transform_operation(left: &Option<Operation>, right: &Option<Operation>) -> Attributes {
-    let attr_l = attributes_from(left);
-    let attr_r = attributes_from(right);
-
-    if attr_l.is_none() {
-        if attr_r.is_none() {
-            return Attributes::Empty;
-        }
-
-        return match attr_r.as_ref().unwrap() {
-            Attributes::Follow => Attributes::Follow,
-            Attributes::Custom(_) => attr_r.unwrap(),
-            Attributes::Empty => Attributes::Empty,
-        };
-    }
-
-    transform_attributes(attr_l.unwrap(), attr_r.unwrap())
-}
-
-pub fn invert_attributes(attr: Attributes, base: Attributes) -> Attributes {
-    let attr = attr.data();
-    let base = base.data();
-
-    if attr.is_none() && base.is_none() {
-        return Attributes::Empty;
-    }
-
-    let attr = attr.unwrap_or(AttributesData::new());
-    let base = base.unwrap_or(AttributesData::new());
-
-    let base_inverted = base
-        .iter()
-        .fold(AttributesData::new(), |mut attributes, (k, v)| {
-            if base.get(k) != attr.get(k) && attr.contains_key(k) {
-                attributes.insert(k.clone(), v.clone());
-            }
-            attributes
-        });
-
-    let inverted = attr.iter().fold(base_inverted, |mut attributes, (k, _)| {
-        if base.get(k) != attr.get(k) && !base.contains_key(k) {
-            // attributes.insert(k.clone(), "".to_owned());
-            attributes.remove(k);
-        }
-        attributes
-    });
-
-    return Attributes::Custom(inverted);
-}
-
-pub fn merge_attributes(attributes: Attributes, other: Attributes) -> Attributes {
-    match (&attributes, &other) {
-        (Attributes::Custom(data), Attributes::Custom(o_data)) => {
-            let mut data = data.clone();
-            data.extend(o_data.clone());
-            Attributes::Custom(data)
-        },
-        (Attributes::Custom(data), _) => Attributes::Custom(data.clone()),
-        _ => other,
-    }
-}
-
-fn compose_attributes(left: Attributes, right: Attributes) -> Attributes {
-    log::trace!("compose_attributes: a: {:?}, b: {:?}", left, right);
-
-    let attr = match (&left, &right) {
-        (_, Attributes::Empty) => Attributes::Empty,
-        (_, Attributes::Custom(_)) => merge_attributes(left, right),
-        (Attributes::Custom(_), _) => merge_attributes(left, right),
-        _ => Attributes::Follow,
-    };
-
-    log::trace!("composed_attributes: a: {:?}", attr);
-    attr.apply_rule()
-}
-
-fn transform_attributes(left: Attributes, right: Attributes) -> Attributes {
-    match (left, right) {
-        (Attributes::Custom(data_l), Attributes::Custom(data_r)) => {
-            let result = data_r
-                .iter()
-                .fold(AttributesData::new(), |mut new_attr_data, (k, v)| {
-                    if !data_l.contains_key(k) {
-                        new_attr_data.insert(k.clone(), v.clone());
-                    }
-                    new_attr_data
-                });
-
-            Attributes::Custom(result)
-        },
-        _ => Attributes::Empty,
-    }
-}

+ 3 - 1
rust-lib/flowy-ot/src/core/delta.rs

@@ -57,6 +57,8 @@ impl FromIterator<Operation> for Delta {
 }
 }
 
 
 impl Delta {
 impl Delta {
+    pub fn new() -> Self { Self::default() }
+
     #[inline]
     #[inline]
     pub fn with_capacity(capacity: usize) -> Self {
     pub fn with_capacity(capacity: usize) -> Self {
         Self {
         Self {
@@ -562,7 +564,7 @@ impl Delta {
         ops
         ops
     }
     }
 
 
-    pub fn attributes_in_interval(&self, interval: Interval) -> Attributes {
+    pub fn get_attributes(&self, interval: Interval) -> Attributes {
         let mut attributes_data = AttributesData::new();
         let mut attributes_data = AttributesData::new();
         let mut offset: usize = 0;
         let mut offset: usize = 0;
 
 

+ 0 - 1
rust-lib/flowy-ot/src/core/mod.rs

@@ -2,7 +2,6 @@ mod attributes;
 mod delta;
 mod delta;
 mod interval;
 mod interval;
 mod operation;
 mod operation;
-mod operation_serde;
 
 
 pub use attributes::*;
 pub use attributes::*;
 pub use delta::*;
 pub use delta::*;

+ 0 - 232
rust-lib/flowy-ot/src/core/operation.rs

@@ -1,232 +0,0 @@
-use crate::core::Attributes;
-use bytecount::num_chars;
-use std::{
-    fmt,
-    ops::{Deref, DerefMut},
-    str::Chars,
-};
-
-#[derive(Debug, Clone, PartialEq)]
-pub enum Operation {
-    Delete(u64),
-    Retain(Retain),
-    Insert(Insert),
-}
-
-impl Operation {
-    pub fn is_delete(&self) -> bool {
-        match self {
-            Operation::Delete(_) => true,
-            _ => false,
-        }
-    }
-
-    pub fn is_noop(&self) -> bool {
-        match self {
-            Operation::Retain(_) => true,
-            _ => false,
-        }
-    }
-
-    pub fn get_attributes(&self) -> Attributes {
-        match self {
-            Operation::Delete(_) => Attributes::Empty,
-            Operation::Retain(retain) => retain.attributes.clone(),
-            Operation::Insert(insert) => insert.attributes.clone(),
-        }
-    }
-
-    pub fn set_attributes(&mut self, attributes: Attributes) {
-        match self {
-            Operation::Delete(_) => {
-                log::error!("Delete should not contains attributes");
-            },
-            Operation::Retain(retain) => {
-                retain.attributes = attributes;
-            },
-            Operation::Insert(insert) => {
-                insert.attributes = attributes;
-            },
-        }
-    }
-
-    pub fn has_attribute(&self) -> bool {
-        match self.get_attributes() {
-            Attributes::Follow => true,
-            Attributes::Custom(_) => false,
-            Attributes::Empty => true,
-        }
-    }
-
-    pub fn length(&self) -> u64 {
-        match self {
-            Operation::Delete(n) => *n,
-            Operation::Retain(r) => r.n,
-            Operation::Insert(i) => i.num_chars(),
-        }
-    }
-
-    pub fn is_empty(&self) -> bool { self.length() == 0 }
-}
-
-impl fmt::Display for Operation {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Operation::Delete(n) => {
-                f.write_fmt(format_args!("delete: {}", n))?;
-            },
-            Operation::Retain(r) => {
-                f.write_fmt(format_args!(
-                    "retain: {}, attributes: {}",
-                    r.n, r.attributes
-                ))?;
-            },
-            Operation::Insert(i) => {
-                f.write_fmt(format_args!(
-                    "insert: {}, attributes: {}",
-                    i.s, i.attributes
-                ))?;
-            },
-        }
-        Ok(())
-    }
-}
-
-pub struct OpBuilder {
-    ty: Operation,
-    attrs: Attributes,
-}
-
-impl OpBuilder {
-    pub fn new(ty: Operation) -> OpBuilder {
-        OpBuilder {
-            ty,
-            attrs: Attributes::Empty,
-        }
-    }
-
-    pub fn retain(n: u64) -> OpBuilder { OpBuilder::new(Operation::Retain(n.into())) }
-
-    pub fn delete(n: u64) -> OpBuilder { OpBuilder::new(Operation::Delete(n)) }
-
-    pub fn insert(s: &str) -> OpBuilder { OpBuilder::new(Operation::Insert(s.into())) }
-
-    pub fn attributes(mut self, attrs: Attributes) -> OpBuilder {
-        self.attrs = attrs;
-        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
-    }
-}
-
-#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
-pub struct Retain {
-    #[serde(rename(serialize = "retain", deserialize = "retain"))]
-    pub n: u64,
-    #[serde(skip_serializing_if = "is_empty")]
-    pub attributes: Attributes,
-}
-
-impl Retain {
-    pub fn merge_or_new_op(&mut self, n: u64, attributes: Attributes) -> Option<Operation> {
-        log::debug!(
-            "merge_retain_or_new_op: {:?}, {:?}",
-            self.attributes,
-            attributes
-        );
-
-        match &attributes {
-            Attributes::Follow => {
-                log::debug!("Follow attribute: {:?}", self.attributes);
-                self.n += n;
-                None
-            },
-            Attributes::Custom(_) | Attributes::Empty => {
-                if self.attributes == attributes {
-                    log::debug!("Attribute equal");
-                    self.n += n;
-                    None
-                } else {
-                    log::debug!("New retain op");
-                    Some(OpBuilder::retain(n).attributes(attributes).build())
-                }
-            },
-        }
-    }
-}
-
-impl std::convert::From<u64> for Retain {
-    fn from(n: u64) -> Self {
-        Retain {
-            n,
-            attributes: Attributes::default(),
-        }
-    }
-}
-
-impl Deref for Retain {
-    type Target = u64;
-
-    fn deref(&self) -> &Self::Target { &self.n }
-}
-
-impl DerefMut for Retain {
-    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.n }
-}
-
-#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
-pub struct Insert {
-    #[serde(rename(serialize = "insert", deserialize = "insert"))]
-    pub s: String,
-
-    #[serde(skip_serializing_if = "is_empty")]
-    pub attributes: Attributes,
-}
-
-impl Insert {
-    pub fn as_bytes(&self) -> &[u8] { self.s.as_bytes() }
-
-    pub fn chars(&self) -> Chars<'_> { self.s.chars() }
-
-    pub fn num_chars(&self) -> u64 { num_chars(self.s.as_bytes()) as _ }
-
-    pub fn merge_or_new_op(&mut self, s: &str, attributes: Attributes) -> Option<Operation> {
-        match &attributes {
-            Attributes::Follow => {
-                self.s += s;
-                return None;
-            },
-            Attributes::Custom(_) | Attributes::Empty => {
-                if self.attributes == attributes {
-                    self.s += s;
-                    None
-                } else {
-                    Some(OpBuilder::insert(s).attributes(attributes).build())
-                }
-            },
-        }
-    }
-}
-
-impl std::convert::From<String> for Insert {
-    fn from(s: String) -> Self {
-        Insert {
-            s,
-            attributes: Attributes::default(),
-        }
-    }
-}
-
-impl std::convert::From<&str> for Insert {
-    fn from(s: &str) -> Self { Insert::from(s.to_owned()) }
-}
-
-fn is_empty(attributes: &Attributes) -> bool { attributes.is_empty() }

+ 0 - 137
rust-lib/flowy-ot/src/core/operation_serde.rs

@@ -1,137 +0,0 @@
-use crate::core::{Attributes, Delta, Operation};
-use serde::{
-    de,
-    de::{MapAccess, SeqAccess, Visitor},
-    ser::{SerializeMap, SerializeSeq},
-    Deserialize,
-    Deserializer,
-    Serialize,
-    Serializer,
-};
-use std::fmt;
-
-impl Serialize for Operation {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        match self {
-            Operation::Retain(retain) => retain.serialize(serializer),
-            Operation::Delete(i) => {
-                let mut map = serializer.serialize_map(Some(1))?;
-                map.serialize_entry("delete", i)?;
-                map.end()
-            },
-            Operation::Insert(insert) => insert.serialize(serializer),
-        }
-    }
-}
-
-impl<'de> Deserialize<'de> for Operation {
-    fn deserialize<D>(deserializer: D) -> Result<Operation, D::Error>
-    where
-        D: Deserializer<'de>,
-    {
-        struct OperationVisitor;
-
-        impl<'de> Visitor<'de> for OperationVisitor {
-            type Value = Operation;
-
-            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-                formatter.write_str("an integer between -2^64 and 2^63 or a string")
-            }
-
-            fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
-            where
-                V: MapAccess<'de>,
-            {
-                let mut operation = None;
-                let mut attributes = None;
-                while let Some(key) = map.next_key()? {
-                    match key {
-                        "delete" => {
-                            if operation.is_some() {
-                                return Err(de::Error::duplicate_field("operation"));
-                            }
-                            operation = Some(Operation::Delete(map.next_value()?));
-                        },
-                        "retain" => {
-                            if operation.is_some() {
-                                return Err(de::Error::duplicate_field("operation"));
-                            }
-                            let i: u64 = map.next_value()?;
-                            operation = Some(Operation::Retain(i.into()));
-                        },
-                        "insert" => {
-                            if operation.is_some() {
-                                return Err(de::Error::duplicate_field("operation"));
-                            }
-                            let i: String = map.next_value()?;
-                            operation = Some(Operation::Insert(i.into()));
-                        },
-                        "attributes" => {
-                            if attributes.is_some() {
-                                return Err(de::Error::duplicate_field("attributes"));
-                            }
-                            let map: Attributes = map.next_value()?;
-                            attributes = Some(map);
-                        },
-                        _ => panic!(),
-                    }
-                }
-                match operation {
-                    None => Err(de::Error::missing_field("operation")),
-                    Some(mut operation) => {
-                        operation.set_attributes(attributes.unwrap_or(Attributes::Empty));
-                        Ok(operation)
-                    },
-                }
-            }
-        }
-
-        deserializer.deserialize_any(OperationVisitor)
-    }
-}
-
-impl Serialize for Delta {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        let mut seq = serializer.serialize_seq(Some(self.ops.len()))?;
-        for op in self.ops.iter() {
-            seq.serialize_element(op)?;
-        }
-        seq.end()
-    }
-}
-
-impl<'de> Deserialize<'de> for Delta {
-    fn deserialize<D>(deserializer: D) -> Result<Delta, D::Error>
-    where
-        D: Deserializer<'de>,
-    {
-        struct OperationSeqVisitor;
-
-        impl<'de> Visitor<'de> for OperationSeqVisitor {
-            type Value = Delta;
-
-            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-                formatter.write_str("a sequence")
-            }
-
-            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
-            where
-                A: SeqAccess<'de>,
-            {
-                let mut o = Delta::default();
-                while let Some(op) = seq.next_element()? {
-                    o.add(op);
-                }
-                Ok(o)
-            }
-        }
-
-        deserializer.deserialize_seq(OperationSeqVisitor)
-    }
-}

+ 7 - 28
rust-lib/flowy-ot/tests/helper/mod.rs

@@ -26,8 +26,8 @@ pub enum TestOp {
     Transform(usize, usize),
     Transform(usize, usize),
 
 
     // invert the delta_a base on the delta_b
     // invert the delta_a base on the delta_b
-    #[display(fmt = "Invert")]
-    Invert(usize, usize),
+    #[display(fmt = "Undo")]
+    Undo(usize, usize),
 
 
     #[display(fmt = "AssertStr")]
     #[display(fmt = "AssertStr")]
     AssertStr(usize, &'static str),
     AssertStr(usize, &'static str),
@@ -91,7 +91,7 @@ impl OpTester {
                 self.deltas[*delta_a_i] = new_delta_a;
                 self.deltas[*delta_a_i] = new_delta_a;
                 self.deltas[*delta_b_i] = new_delta_b;
                 self.deltas[*delta_b_i] = new_delta_b;
             },
             },
-            TestOp::Invert(delta_a_i, delta_b_i) => {
+            TestOp::Undo(delta_a_i, delta_b_i) => {
                 let delta_a = &self.deltas[*delta_a_i];
                 let delta_a = &self.deltas[*delta_a_i];
                 let delta_b = &self.deltas[*delta_b_i];
                 let delta_b = &self.deltas[*delta_b_i];
                 log::debug!("Invert: ");
                 log::debug!("Invert: ");
@@ -149,7 +149,7 @@ impl OpTester {
             log::error!("{} out of bounds {}", index, target_interval);
             log::error!("{} out of bounds {}", index, target_interval);
         }
         }
 
 
-        let mut attributes = old_delta.attributes_in_interval(Interval::new(index, index + 1));
+        let mut attributes = old_delta.get_attributes(Interval::new(index, index + 1));
         if attributes == Attributes::Empty {
         if attributes == Attributes::Empty {
             attributes = Attributes::Follow;
             attributes = Attributes::Follow;
         }
         }
@@ -165,7 +165,7 @@ impl OpTester {
         interval: &Interval,
         interval: &Interval,
     ) {
     ) {
         let old_delta = &self.deltas[delta_index];
         let old_delta = &self.deltas[delta_index];
-        let old_attributes = old_delta.attributes_in_interval(*interval);
+        let old_attributes = old_delta.get_attributes(*interval);
         log::debug!(
         log::debug!(
             "merge attributes: {:?}, with old: {:?}",
             "merge attributes: {:?}, with old: {:?}",
             attributes,
             attributes,
@@ -211,7 +211,7 @@ fn new_delta_with_op(delta: &Delta, op: Operation, interval: Interval) -> Delta
     if prefix.is_empty() == false && prefix != interval {
     if prefix.is_empty() == false && prefix != interval {
         let intervals = split_interval_with_delta(delta, &prefix);
         let intervals = split_interval_with_delta(delta, &prefix);
         intervals.into_iter().for_each(|p_interval| {
         intervals.into_iter().for_each(|p_interval| {
-            let attributes = delta.attributes_in_interval(p_interval);
+            let attributes = delta.get_attributes(p_interval);
             log::debug!(
             log::debug!(
                 "prefix attribute: {:?}, interval: {:?}",
                 "prefix attribute: {:?}, interval: {:?}",
                 attributes,
                 attributes,
@@ -228,7 +228,7 @@ fn new_delta_with_op(delta: &Delta, op: Operation, interval: Interval) -> Delta
     if suffix.is_empty() == false {
     if suffix.is_empty() == false {
         let intervals = split_interval_with_delta(delta, &suffix);
         let intervals = split_interval_with_delta(delta, &suffix);
         intervals.into_iter().for_each(|s_interval| {
         intervals.into_iter().for_each(|s_interval| {
-            let attributes = delta.attributes_in_interval(s_interval);
+            let attributes = delta.get_attributes(s_interval);
             log::debug!(
             log::debug!(
                 "suffix attribute: {:?}, interval: {:?}",
                 "suffix attribute: {:?}, interval: {:?}",
                 attributes,
                 attributes,
@@ -241,27 +241,6 @@ fn new_delta_with_op(delta: &Delta, op: Operation, interval: Interval) -> Delta
     delta.compose(&new_delta).unwrap()
     delta.compose(&new_delta).unwrap()
 }
 }
 
 
-fn split_interval_with_delta(delta: &Delta, interval: &Interval) -> Vec<Interval> {
-    let mut start = 0;
-    let mut new_intervals = vec![];
-    delta.ops.iter().for_each(|op| match op {
-        Operation::Delete(_) => {},
-        Operation::Retain(_) => {},
-        Operation::Insert(insert) => {
-            let len = insert.num_chars() as usize;
-            let end = start + len;
-            let insert_interval = Interval::new(start, end);
-            let new_interval = interval.intersect(insert_interval);
-
-            if !new_interval.is_empty() {
-                new_intervals.push(new_interval)
-            }
-            start += len;
-        },
-    });
-    new_intervals
-}
-
 pub fn target_length_split_with_interval(
 pub fn target_length_split_with_interval(
     length: usize,
     length: usize,
     interval: Interval,
     interval: Interval,

+ 71 - 7
rust-lib/flowy-ot/tests/invert_test.rs

@@ -3,7 +3,7 @@ use crate::helper::{TestOp::*, *};
 use flowy_ot::core::{Delta, Interval, OpBuilder};
 use flowy_ot::core::{Delta, Interval, OpBuilder};
 
 
 #[test]
 #[test]
-fn delta_invert_delta_test() {
+fn delta_invert_no_attribute_delta() {
     let mut delta = Delta::default();
     let mut delta = Delta::default();
     delta.add(OpBuilder::insert("123").build());
     delta.add(OpBuilder::insert("123").build());
 
 
@@ -19,31 +19,31 @@ fn delta_invert_delta_test() {
 }
 }
 
 
 #[test]
 #[test]
-fn delta_invert_delta_test2() {
+fn delta_invert_no_attribute_delta2() {
     let ops = vec![
     let ops = vec![
         Insert(0, "123", 0),
         Insert(0, "123", 0),
         Insert(1, "4567", 0),
         Insert(1, "4567", 0),
-        Invert(0, 1),
+        Undo(0, 1),
         AssertOpsJson(0, r#"[{"insert":"123"}]"#),
         AssertOpsJson(0, r#"[{"insert":"123"}]"#),
     ];
     ];
     OpTester::new().run_script(ops);
     OpTester::new().run_script(ops);
 }
 }
 
 
 #[test]
 #[test]
-fn delta_invert_delta_with_attribute() {
+fn delta_invert_attribute_delta_with_no_attribute_delta() {
     let ops = vec![
     let ops = vec![
         Insert(0, "123", 0),
         Insert(0, "123", 0),
         Bold(0, Interval::new(0, 3), true),
         Bold(0, Interval::new(0, 3), true),
         AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
         AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
         Insert(1, "4567", 0),
         Insert(1, "4567", 0),
-        Invert(0, 1),
+        Undo(0, 1),
         AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
         AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
     ];
     ];
     OpTester::new().run_script(ops);
     OpTester::new().run_script(ops);
 }
 }
 
 
 #[test]
 #[test]
-fn delta_invert_delta() {
+fn delta_invert_attribute_delta_with_no_attribute_delta2() {
     let ops = vec![
     let ops = vec![
         Insert(0, "123", 0),
         Insert(0, "123", 0),
         Bold(0, Interval::new(0, 3), true),
         Bold(0, Interval::new(0, 3), true),
@@ -55,7 +55,71 @@ fn delta_invert_delta() {
             r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34","attributes":{"bold":"true","italic":"true"}},{"insert":"56","attributes":{"bold":"true"}}]"#,
             r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34","attributes":{"bold":"true","italic":"true"}},{"insert":"56","attributes":{"bold":"true"}}]"#,
         ),
         ),
         Insert(1, "abc", 0),
         Insert(1, "abc", 0),
-        Invert(0, 1),
+        Undo(0, 1),
+        AssertOpsJson(
+            0,
+            r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34","attributes":{"bold":"true","italic":"true"}},{"insert":"56","attributes":{"bold":"true"}}]"#,
+        ),
+    ];
+    OpTester::new().run_script(ops);
+}
+
+#[test]
+fn delta_invert_no_attribute_delta_with_attribute_delta() {
+    let ops = vec![
+        Insert(0, "123", 0),
+        Insert(1, "4567", 0),
+        Bold(1, Interval::new(0, 3), true),
+        AssertOpsJson(
+            1,
+            r#"[{"insert":"456","attributes":{"bold":"true"}},{"insert":"7"}]"#,
+        ),
+        Undo(0, 1),
+        AssertOpsJson(0, r#"[{"insert":"123"}]"#),
+    ];
+    OpTester::new().run_script(ops);
+}
+
+#[test]
+fn delta_invert_no_attribute_delta_with_attribute_delta2() {
+    let ops = vec![
+        Insert(0, "123", 0),
+        AssertOpsJson(0, r#"[{"insert":"123"}]"#),
+        Insert(1, "abc", 0),
+        Bold(1, Interval::new(0, 3), true),
+        Insert(1, "d", 3),
+        Italic(1, Interval::new(1, 3), true),
+        AssertOpsJson(
+            1,
+            r#"[{"insert":"a","attributes":{"bold":"true"}},{"insert":"bc","attributes":{"bold":"true","italic":"true"}},{"insert":"d","attributes":{"bold":"true"}}]"#,
+        ),
+        Undo(0, 1),
+        AssertOpsJson(0, r#"[{"insert":"123"}]"#),
+    ];
+    OpTester::new().run_script(ops);
+}
+
+#[test]
+fn delta_invert_attribute_delta_with_attribute_delta() {
+    let ops = vec![
+        Insert(0, "123", 0),
+        Bold(0, Interval::new(0, 3), true),
+        Insert(0, "456", 3),
+        AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
+        Italic(0, Interval::new(2, 4), true),
+        AssertOpsJson(
+            0,
+            r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34","attributes":{"bold":"true","italic":"true"}},{"insert":"56","attributes":{"bold":"true"}}]"#,
+        ),
+        Insert(1, "abc", 0),
+        Bold(1, Interval::new(0, 3), true),
+        Insert(1, "d", 3),
+        Italic(1, Interval::new(1, 3), true),
+        AssertOpsJson(
+            1,
+            r#"[{"insert":"a","attributes":{"bold":"true"}},{"insert":"bc","attributes":{"bold":"true","italic":"true"}},{"insert":"d","attributes":{"bold":"true"}}]"#,
+        ),
+        Undo(0, 1),
         AssertOpsJson(
         AssertOpsJson(
             0,
             0,
             r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34","attributes":{"bold":"true","italic":"true"}},{"insert":"56","attributes":{"bold":"true"}}]"#,
             r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34","attributes":{"bold":"true","italic":"true"}},{"insert":"56","attributes":{"bold":"true"}}]"#,