add attribute iterator

This commit is contained in:
appflowy 2021-08-11 11:42:46 +08:00
parent 15c3a821ec
commit 039b4917ed
9 changed files with 162 additions and 63 deletions

View File

@ -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 {

View File

@ -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);
}

View File

@ -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!()
}
}

View File

@ -1,6 +1,7 @@
mod extension;
mod insert_ext;
mod view;
pub use extension::*;
pub use insert_ext::*;
pub use view::*;

View File

@ -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()),
]
}

View File

@ -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 {

View File

@ -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);

View File

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

View File

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