2021-08-05 20:05:40 +08:00
|
|
|
use crate::{
|
2021-08-18 16:04:22 +08:00
|
|
|
client::{view::View, History, RevId, UndoResult, RECORD_THRESHOLD},
|
2021-08-10 11:22:57 +08:00
|
|
|
core::*,
|
2021-08-15 00:05:18 +08:00
|
|
|
errors::{ErrorBuilder, OTError, OTErrorCode, OTErrorCode::*},
|
2021-08-05 20:05:40 +08:00
|
|
|
};
|
2021-09-14 16:22:44 +08:00
|
|
|
use std::convert::TryInto;
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-18 16:04:22 +08:00
|
|
|
pub trait DocumentData {
|
|
|
|
fn into_string(self) -> Result<String, OTError>;
|
|
|
|
}
|
2021-08-10 11:22:57 +08:00
|
|
|
|
2021-09-13 16:45:36 +08:00
|
|
|
pub trait CustomDocument {
|
|
|
|
fn init_delta() -> Delta;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct PlainDoc();
|
|
|
|
impl CustomDocument for PlainDoc {
|
|
|
|
fn init_delta() -> Delta { Delta::new() }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct FlowyDoc();
|
|
|
|
impl CustomDocument for FlowyDoc {
|
|
|
|
fn init_delta() -> Delta { DeltaBuilder::new().insert("\n").build() }
|
|
|
|
}
|
|
|
|
|
2021-08-05 20:05:40 +08:00
|
|
|
pub struct Document {
|
2021-08-11 11:42:46 +08:00
|
|
|
delta: Delta,
|
2021-08-05 20:05:40 +08:00
|
|
|
history: History,
|
2021-08-11 11:42:46 +08:00
|
|
|
view: View,
|
2021-08-06 23:06:27 +08:00
|
|
|
rev_id_counter: usize,
|
2021-08-10 11:22:57 +08:00
|
|
|
last_edit_time: usize,
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Document {
|
2021-09-13 16:45:36 +08:00
|
|
|
pub fn new<C: CustomDocument>() -> Self { Self::from_delta(C::init_delta()) }
|
2021-08-11 23:34:35 +08:00
|
|
|
|
|
|
|
pub fn from_delta(delta: Delta) -> Self {
|
2021-08-05 20:05:40 +08:00
|
|
|
Document {
|
2021-08-11 11:42:46 +08:00
|
|
|
delta,
|
2021-08-05 20:05:40 +08:00
|
|
|
history: History::new(),
|
2021-08-11 11:42:46 +08:00
|
|
|
view: View::new(),
|
2021-08-05 22:52:19 +08:00
|
|
|
rev_id_counter: 1,
|
2021-08-10 11:22:57 +08:00
|
|
|
last_edit_time: 0,
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-12 22:19:59 +08:00
|
|
|
pub fn from_json(json: &str) -> Result<Self, OTError> {
|
|
|
|
let delta = Delta::from_json(json)?;
|
|
|
|
Ok(Self::from_delta(delta))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn to_json(&self) -> String { self.delta.to_json() }
|
|
|
|
|
2021-09-14 16:22:44 +08:00
|
|
|
pub fn apply_changeset<T>(&mut self, changeset: T) -> Result<(), OTError>
|
|
|
|
where
|
|
|
|
T: TryInto<Delta, Error = OTError>,
|
|
|
|
{
|
|
|
|
let new_delta: Delta = changeset.try_into()?;
|
|
|
|
self.add_delta(&new_delta);
|
|
|
|
|
|
|
|
log::info!("Current delta: {:?}", self.to_json());
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-08-18 16:04:22 +08:00
|
|
|
pub fn insert<T: DocumentData>(&mut self, index: usize, data: T) -> Result<Delta, OTError> {
|
2021-08-15 00:05:18 +08:00
|
|
|
let interval = Interval::new(index, index);
|
|
|
|
let _ = validate_interval(&self.delta, &interval)?;
|
2021-08-18 16:04:22 +08:00
|
|
|
|
|
|
|
let text = data.into_string()?;
|
|
|
|
let delta = self.view.insert(&self.delta, &text, interval)?;
|
2021-08-15 21:11:48 +08:00
|
|
|
log::debug!("👉 receive change: {}", delta);
|
2021-08-14 16:44:39 +08:00
|
|
|
self.add_delta(&delta)?;
|
|
|
|
Ok(delta)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn delete(&mut self, interval: Interval) -> Result<Delta, OTError> {
|
2021-08-15 00:05:18 +08:00
|
|
|
let _ = validate_interval(&self.delta, &interval)?;
|
2021-08-14 16:44:39 +08:00
|
|
|
debug_assert_eq!(interval.is_empty(), false);
|
|
|
|
let delete = self.view.delete(&self.delta, interval)?;
|
|
|
|
if !delete.is_empty() {
|
2021-08-15 21:11:48 +08:00
|
|
|
log::debug!("👉 receive change: {}", delete);
|
2021-08-14 16:44:39 +08:00
|
|
|
let _ = self.add_delta(&delete)?;
|
|
|
|
}
|
|
|
|
Ok(delete)
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
2021-08-11 17:18:10 +08:00
|
|
|
pub fn format(&mut self, interval: Interval, attribute: Attribute) -> Result<(), OTError> {
|
2021-08-15 00:05:18 +08:00
|
|
|
let _ = validate_interval(&self.delta, &interval)?;
|
2021-08-11 17:18:10 +08:00
|
|
|
log::debug!("format with {} at {}", attribute, interval);
|
2021-09-12 22:19:59 +08:00
|
|
|
let format_delta = self.view.format(&self.delta, attribute.clone(), interval).unwrap();
|
2021-08-14 16:44:39 +08:00
|
|
|
|
2021-08-15 21:11:48 +08:00
|
|
|
log::debug!("👉 receive change: {}", format_delta);
|
2021-08-14 16:44:39 +08:00
|
|
|
self.add_delta(&format_delta)?;
|
|
|
|
Ok(())
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
2021-09-12 22:19:59 +08:00
|
|
|
pub fn replace<T: DocumentData>(&mut self, interval: Interval, data: T) -> Result<Delta, OTError> {
|
2021-08-15 00:05:18 +08:00
|
|
|
let _ = validate_interval(&self.delta, &interval)?;
|
2021-08-11 08:40:58 +08:00
|
|
|
let mut delta = Delta::default();
|
2021-08-18 16:04:22 +08:00
|
|
|
let text = data.into_string()?;
|
2021-08-15 00:05:18 +08:00
|
|
|
if !text.is_empty() {
|
2021-08-18 16:04:22 +08:00
|
|
|
delta = self.view.insert(&self.delta, &text, interval)?;
|
2021-08-15 21:11:48 +08:00
|
|
|
log::debug!("👉 receive change: {}", delta);
|
2021-08-15 00:05:18 +08:00
|
|
|
self.add_delta(&delta)?;
|
2021-08-11 08:40:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if !interval.is_empty() {
|
2021-08-14 16:44:39 +08:00
|
|
|
let delete = self.delete(interval)?;
|
|
|
|
delta = delta.compose(&delete)?;
|
2021-08-11 08:40:58 +08:00
|
|
|
}
|
|
|
|
|
2021-08-14 16:44:39 +08:00
|
|
|
Ok(delta)
|
2021-08-11 08:40:58 +08:00
|
|
|
}
|
|
|
|
|
2021-08-05 22:52:19 +08:00
|
|
|
pub fn can_undo(&self) -> bool { self.history.can_undo() }
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-05 22:52:19 +08:00
|
|
|
pub fn can_redo(&self) -> bool { self.history.can_redo() }
|
|
|
|
|
|
|
|
pub fn undo(&mut self) -> Result<UndoResult, OTError> {
|
|
|
|
match self.history.undo() {
|
2021-09-12 22:19:59 +08:00
|
|
|
None => Err(ErrorBuilder::new(UndoFail).msg("Undo stack is empty").build()),
|
2021-08-05 22:52:19 +08:00
|
|
|
Some(undo_delta) => {
|
2021-08-10 11:22:57 +08:00
|
|
|
let (new_delta, inverted_delta) = self.invert_change(&undo_delta)?;
|
|
|
|
let result = UndoResult::success(new_delta.target_len as usize);
|
2021-08-11 11:42:46 +08:00
|
|
|
self.delta = new_delta;
|
2021-08-10 11:22:57 +08:00
|
|
|
self.history.add_redo(inverted_delta);
|
2021-08-05 22:52:19 +08:00
|
|
|
|
|
|
|
Ok(result)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn redo(&mut self) -> Result<UndoResult, OTError> {
|
|
|
|
match self.history.redo() {
|
|
|
|
None => Err(ErrorBuilder::new(RedoFail).build()),
|
|
|
|
Some(redo_delta) => {
|
2021-08-10 11:22:57 +08:00
|
|
|
let (new_delta, inverted_delta) = self.invert_change(&redo_delta)?;
|
2021-08-06 23:06:27 +08:00
|
|
|
let result = UndoResult::success(new_delta.target_len as usize);
|
2021-08-11 11:42:46 +08:00
|
|
|
self.delta = new_delta;
|
2021-08-08 22:29:16 +08:00
|
|
|
|
2021-08-10 11:22:57 +08:00
|
|
|
self.history.add_undo(inverted_delta);
|
2021-08-05 22:52:19 +08:00
|
|
|
Ok(result)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-11 11:42:46 +08:00
|
|
|
pub fn to_string(&self) -> String { self.delta.apply("").unwrap() }
|
2021-08-06 22:25:09 +08:00
|
|
|
|
2021-08-11 11:42:46 +08:00
|
|
|
pub fn data(&self) -> &Delta { &self.delta }
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-11 11:42:46 +08:00
|
|
|
pub fn set_data(&mut self, data: Delta) { self.delta = data; }
|
2021-08-15 00:05:18 +08:00
|
|
|
}
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-15 00:05:18 +08:00
|
|
|
impl Document {
|
2021-08-14 16:44:39 +08:00
|
|
|
fn add_delta(&mut self, delta: &Delta) -> Result<(), OTError> {
|
2021-08-13 14:13:31 +08:00
|
|
|
let composed_delta = self.delta.compose(delta)?;
|
|
|
|
let mut undo_delta = delta.invert(&self.delta);
|
2021-08-10 11:22:57 +08:00
|
|
|
self.rev_id_counter += 1;
|
|
|
|
|
|
|
|
let now = chrono::Utc::now().timestamp_millis() as usize;
|
|
|
|
if now - self.last_edit_time < RECORD_THRESHOLD {
|
|
|
|
if let Some(last_delta) = self.history.undo() {
|
|
|
|
log::debug!("compose previous change");
|
|
|
|
log::debug!("current = {}", undo_delta);
|
|
|
|
log::debug!("previous = {}", last_delta);
|
|
|
|
undo_delta = undo_delta.compose(&last_delta)?;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.last_edit_time = now;
|
|
|
|
}
|
|
|
|
|
2021-08-15 21:11:48 +08:00
|
|
|
log::debug!("👉 receive change undo: {}", undo_delta);
|
2021-08-10 11:22:57 +08:00
|
|
|
if !undo_delta.is_empty() {
|
|
|
|
self.history.record(undo_delta);
|
|
|
|
}
|
|
|
|
|
2021-08-10 14:24:41 +08:00
|
|
|
log::debug!("document delta: {}", &composed_delta);
|
2021-08-14 16:44:39 +08:00
|
|
|
self.delta = composed_delta;
|
|
|
|
Ok(())
|
2021-08-10 11:22:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn invert_change(&self, change: &Delta) -> Result<(Delta, Delta), OTError> {
|
|
|
|
// c = a.compose(b)
|
|
|
|
// d = b.invert(a)
|
|
|
|
// a = c.compose(d)
|
|
|
|
log::debug!("👉invert change {}", change);
|
2021-08-11 11:42:46 +08:00
|
|
|
let new_delta = self.delta.compose(change)?;
|
|
|
|
let inverted_delta = change.invert(&self.delta);
|
2021-08-10 11:22:57 +08:00
|
|
|
Ok((new_delta, inverted_delta))
|
|
|
|
}
|
2021-08-15 00:05:18 +08:00
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
fn next_rev_id(&self) -> RevId { RevId(self.rev_id_counter) }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn validate_interval(delta: &Delta, interval: &Interval) -> Result<(), OTError> {
|
|
|
|
if delta.target_len < interval.end {
|
2021-09-12 22:19:59 +08:00
|
|
|
log::error!("{:?} out of bounds. should 0..{}", interval, delta.target_len);
|
2021-08-15 00:05:18 +08:00
|
|
|
return Err(ErrorBuilder::new(OTErrorCode::IntervalOutOfBound).build());
|
|
|
|
}
|
|
|
|
Ok(())
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|