compare delta between flutter and rust

This commit is contained in:
appflowy 2021-09-15 16:35:40 +08:00
parent 0edd442562
commit 87d3f4fc0d
20 changed files with 117 additions and 75 deletions

View file

@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:flowy_editor/flowy_editor.dart'; import 'package:flowy_editor/flowy_editor.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
// ignore: implementation_imports
import 'package:flowy_editor/src/model/quill_delta.dart'; import 'package:flowy_editor/src/model/quill_delta.dart';
import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/protobuf/flowy-document/doc.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-document/doc.pb.dart';
@ -18,16 +19,29 @@ class FlowyDoc implements EditorChangesetSender {
String get id => doc.id; String get id => doc.id;
@override @override
void sendDelta(Delta delta) { void sendDelta(Delta changeset, Delta delta) async {
final json = jsonEncode(delta.toJson()); final json = jsonEncode(changeset.toJson());
Log.debug("Send json: $json"); Log.debug("Send json: $json");
iDocImpl.applyChangeset(json: json); final result = await iDocImpl.applyChangeset(json: json);
result.fold((rustDoc) {
// final json = utf8.decode(doc.data);
final rustDelta = Delta.fromJson(jsonDecode(utf8.decode(rustDoc.data)));
if (delta != rustDelta) {
Log.error("Receive : $rustDelta");
Log.error("Expected : $delta");
} else {
Log.info("Receive : $rustDelta");
Log.info("Expected : $delta");
}
}, (r) => null);
} }
} }
abstract class IDoc { abstract class IDoc {
Future<Either<Doc, WorkspaceError>> readDoc(); Future<Either<Doc, WorkspaceError>> readDoc();
Future<Either<Unit, WorkspaceError>> saveDoc({String? json}); Future<Either<Unit, WorkspaceError>> saveDoc({String? json});
Future<Either<Unit, WorkspaceError>> applyChangeset({String? json}); Future<Either<Doc, WorkspaceError>> applyChangeset({String? json});
Future<Either<Unit, WorkspaceError>> closeDoc(); Future<Either<Unit, WorkspaceError>> closeDoc();
} }

View file

@ -33,7 +33,7 @@ class IDocImpl extends IDoc {
} }
@override @override
Future<Either<Unit, WorkspaceError>> applyChangeset({String? json}) { Future<Either<Doc, WorkspaceError>> applyChangeset({String? json}) {
return repo.applyChangeset(data: _encodeText(json)); return repo.applyChangeset(data: _encodeText(json));
} }
} }

View file

@ -25,7 +25,7 @@ class DocRepository {
return WorkspaceEventSaveViewData(request).send(); return WorkspaceEventSaveViewData(request).send();
} }
Future<Either<Unit, WorkspaceError>> applyChangeset( Future<Either<Doc, WorkspaceError>> applyChangeset(
{required Uint8List data}) { {required Uint8List data}) {
final request = ApplyChangesetRequest.create() final request = ApplyChangesetRequest.create()
..viewId = docId ..viewId = docId

View file

@ -15,7 +15,7 @@ import 'node/node.dart';
import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_log/flowy_log.dart';
abstract class EditorChangesetSender { abstract class EditorChangesetSender {
void sendDelta(Delta delta); void sendDelta(Delta changeset, Delta delta);
} }
/// The rich text document /// The rich text document
@ -182,8 +182,11 @@ class Document {
} }
try { try {
sender?.sendDelta(delta); final changeset = delta;
_delta = _delta.compose(delta); _delta = _delta.compose(delta);
sender?.sendDelta(changeset, _delta);
} catch (e) { } catch (e) {
throw '_delta compose failed'; throw '_delta compose failed';
} }

View file

@ -275,14 +275,14 @@ class WorkspaceEventApplyChangeset {
ApplyChangesetRequest request; ApplyChangesetRequest request;
WorkspaceEventApplyChangeset(this.request); WorkspaceEventApplyChangeset(this.request);
Future<Either<Unit, WorkspaceError>> send() { Future<Either<Doc, WorkspaceError>> send() {
final request = FFIRequest.create() final request = FFIRequest.create()
..event = WorkspaceEvent.ApplyChangeset.toString() ..event = WorkspaceEvent.ApplyChangeset.toString()
..payload = requestToBytes(this.request); ..payload = requestToBytes(this.request);
return Dispatch.asyncRequest(request) return Dispatch.asyncRequest(request)
.then((bytesResult) => bytesResult.fold( .then((bytesResult) => bytesResult.fold(
(bytes) => left(unit), (okBytes) => left(Doc.fromBuffer(okBytes)),
(errBytes) => right(WorkspaceError.fromBuffer(errBytes)), (errBytes) => right(WorkspaceError.fromBuffer(errBytes)),
)); ));
} }

View file

@ -9,6 +9,7 @@ use crate::{
}; };
use diesel::SqliteConnection; use diesel::SqliteConnection;
use flowy_database::ConnectionPool; use flowy_database::ConnectionPool;
use flowy_ot::client::Document;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::RwLock; use tokio::sync::RwLock;
@ -54,15 +55,25 @@ impl FlowyDocument {
Ok(()) Ok(())
} }
pub async fn apply_changeset(&self, params: ApplyChangesetParams) -> Result<(), DocError> { pub async fn apply_changeset(&self, params: ApplyChangesetParams) -> Result<Doc, DocError> {
let _ = self let _ = self
.cache .cache
.mut_doc(&params.id, |doc| { .mut_doc(&params.id, |doc| {
log::debug!("Document:{} applying delta", &params.id);
let _ = doc.apply_changeset(params.data.clone())?; let _ = doc.apply_changeset(params.data.clone())?;
Ok(()) Ok(())
}) })
.await?; .await?;
Ok(())
let doc_str = match self.cache.read_doc(&params.id).await? {
None => "".to_owned(),
Some(doc_json) => doc_json,
};
let doc = Doc {
id: params.id,
data: doc_str.as_bytes().to_vec(),
};
Ok(doc)
} }
} }

View file

@ -11,7 +11,7 @@ use tokio::sync::RwLock;
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct DocId(pub(crate) String); pub struct DocId(pub(crate) String);
pub struct DocInfo { pub struct OpenDocument {
document: Document, document: Document,
} }
@ -23,7 +23,7 @@ where
} }
pub(crate) struct DocCache { pub(crate) struct DocCache {
inner: DashMap<DocId, RwLock<DocInfo>>, inner: DashMap<DocId, RwLock<OpenDocument>>,
} }
impl DocCache { impl DocCache {
@ -37,7 +37,7 @@ impl DocCache {
let doc_id = id.into(); let doc_id = id.into();
let delta = data.try_into()?; let delta = data.try_into()?;
let document = Document::from_delta(delta); let document = Document::from_delta(delta);
let doc_info = DocInfo { document }; let doc_info = OpenDocument { document };
self.inner.insert(doc_id, RwLock::new(doc_info)); self.inner.insert(doc_id, RwLock::new(doc_info));
Ok(()) Ok(())
} }
@ -49,9 +49,7 @@ impl DocCache {
{ {
let doc_id = id.into(); let doc_id = id.into();
match self.inner.get(&doc_id) { match self.inner.get(&doc_id) {
None => Err(ErrorBuilder::new(ErrorCode::DocNotfound) None => Err(doc_not_found()),
.msg("Doc is close or you should call open first")
.build()),
Some(doc_info) => { Some(doc_info) => {
let mut write_guard = doc_info.write().await; let mut write_guard = doc_info.write().await;
f(&mut write_guard.document) f(&mut write_guard.document)
@ -59,6 +57,21 @@ impl DocCache {
} }
} }
pub(crate) async fn read_doc<T>(&self, id: T) -> Result<Option<String>, DocError>
where
T: Into<DocId>,
{
let doc_id = id.into();
match self.inner.get(&doc_id) {
None => Err(doc_not_found()),
Some(doc_info) => {
let mut write_guard = doc_info.read().await;
let doc = &(*write_guard).document;
Ok(Some(doc.to_json()))
},
}
}
pub(crate) fn close<T>(&self, id: T) -> Result<(), DocError> pub(crate) fn close<T>(&self, id: T) -> Result<(), DocError>
where where
T: Into<DocId>, T: Into<DocId>,
@ -68,3 +81,9 @@ impl DocCache {
Ok(()) Ok(())
} }
} }
fn doc_not_found() -> DocError {
ErrorBuilder::new(ErrorCode::DocNotfound)
.msg("Doc is close or you should call open first")
.build()
}

View file

@ -51,14 +51,16 @@ impl Document {
pub fn to_json(&self) -> String { self.delta.to_json() } pub fn to_json(&self) -> String { self.delta.to_json() }
pub fn to_string(&self) -> String { self.delta.apply("").unwrap() }
pub fn apply_changeset<T>(&mut self, changeset: T) -> Result<(), OTError> pub fn apply_changeset<T>(&mut self, changeset: T) -> Result<(), OTError>
where where
T: TryInto<Delta, Error = OTError>, T: TryInto<Delta, Error = OTError>,
{ {
let new_delta: Delta = changeset.try_into()?; let new_delta: Delta = changeset.try_into()?;
log::debug!("Apply delta: {}", new_delta);
self.add_delta(&new_delta); self.add_delta(&new_delta);
log::debug!("Current delta: {}", self.to_json());
log::info!("Current delta: {:?}", self.to_json());
Ok(()) Ok(())
} }
@ -68,7 +70,7 @@ impl Document {
let text = data.into_string()?; let text = data.into_string()?;
let delta = self.view.insert(&self.delta, &text, interval)?; let delta = self.view.insert(&self.delta, &text, interval)?;
log::debug!("👉 receive change: {}", delta); log::trace!("👉 receive change: {}", delta);
self.add_delta(&delta)?; self.add_delta(&delta)?;
Ok(delta) Ok(delta)
} }
@ -78,7 +80,7 @@ impl Document {
debug_assert_eq!(interval.is_empty(), false); debug_assert_eq!(interval.is_empty(), false);
let delete = self.view.delete(&self.delta, interval)?; let delete = self.view.delete(&self.delta, interval)?;
if !delete.is_empty() { if !delete.is_empty() {
log::debug!("👉 receive change: {}", delete); log::trace!("👉 receive change: {}", delete);
let _ = self.add_delta(&delete)?; let _ = self.add_delta(&delete)?;
} }
Ok(delete) Ok(delete)
@ -86,10 +88,10 @@ impl Document {
pub fn format(&mut self, interval: Interval, attribute: Attribute) -> Result<(), OTError> { pub fn format(&mut self, interval: Interval, attribute: Attribute) -> Result<(), OTError> {
let _ = validate_interval(&self.delta, &interval)?; let _ = validate_interval(&self.delta, &interval)?;
log::debug!("format with {} at {}", attribute, interval); log::trace!("format with {} at {}", attribute, interval);
let format_delta = self.view.format(&self.delta, attribute.clone(), interval).unwrap(); let format_delta = self.view.format(&self.delta, attribute.clone(), interval).unwrap();
log::debug!("👉 receive change: {}", format_delta); log::trace!("👉 receive change: {}", format_delta);
self.add_delta(&format_delta)?; self.add_delta(&format_delta)?;
Ok(()) Ok(())
} }
@ -100,7 +102,7 @@ impl Document {
let text = data.into_string()?; let text = data.into_string()?;
if !text.is_empty() { if !text.is_empty() {
delta = self.view.insert(&self.delta, &text, interval)?; delta = self.view.insert(&self.delta, &text, interval)?;
log::debug!("👉 receive change: {}", delta); log::trace!("👉 receive change: {}", delta);
self.add_delta(&delta)?; self.add_delta(&delta)?;
} }
@ -144,8 +146,6 @@ impl Document {
} }
} }
pub fn to_string(&self) -> String { self.delta.apply("").unwrap() }
pub fn data(&self) -> &Delta { &self.delta } pub fn data(&self) -> &Delta { &self.delta }
pub fn set_data(&mut self, data: Delta) { self.delta = data; } pub fn set_data(&mut self, data: Delta) { self.delta = data; }
@ -160,21 +160,21 @@ impl Document {
let now = chrono::Utc::now().timestamp_millis() as usize; let now = chrono::Utc::now().timestamp_millis() as usize;
if now - self.last_edit_time < RECORD_THRESHOLD { if now - self.last_edit_time < RECORD_THRESHOLD {
if let Some(last_delta) = self.history.undo() { if let Some(last_delta) = self.history.undo() {
log::debug!("compose previous change"); log::trace!("compose previous change");
log::debug!("current = {}", undo_delta); log::trace!("current = {}", undo_delta);
log::debug!("previous = {}", last_delta); log::trace!("previous = {}", last_delta);
undo_delta = undo_delta.compose(&last_delta)?; undo_delta = undo_delta.compose(&last_delta)?;
} }
} else { } else {
self.last_edit_time = now; self.last_edit_time = now;
} }
log::debug!("👉 receive change undo: {}", undo_delta); log::trace!("👉 receive change undo: {}", undo_delta);
if !undo_delta.is_empty() { if !undo_delta.is_empty() {
self.history.record(undo_delta); self.history.record(undo_delta);
} }
log::debug!("document delta: {}", &composed_delta); log::trace!("document delta: {}", &composed_delta);
self.delta = composed_delta; self.delta = composed_delta;
Ok(()) Ok(())
} }
@ -183,7 +183,7 @@ impl Document {
// c = a.compose(b) // c = a.compose(b)
// d = b.invert(a) // d = b.invert(a)
// a = c.compose(d) // a = c.compose(d)
log::debug!("👉invert change {}", change); log::trace!("👉invert change {}", change);
let new_delta = self.delta.compose(change)?; let new_delta = self.delta.compose(change)?;
let inverted_delta = change.invert(&self.delta); let inverted_delta = change.invert(&self.delta);
Ok((new_delta, inverted_delta)) Ok((new_delta, inverted_delta))

View file

@ -25,7 +25,7 @@ impl View {
let mut new_delta = None; let mut new_delta = None;
for ext in &self.insert_exts { for ext in &self.insert_exts {
if let Some(delta) = ext.apply(delta, interval.size(), text, interval.start) { if let Some(delta) = ext.apply(delta, interval.size(), text, interval.start) {
log::debug!("[{}]: applied, delta: {}", ext.ext_name(), delta); log::trace!("[{}]: applied, delta: {}", ext.ext_name(), delta);
new_delta = Some(delta); new_delta = Some(delta);
break; break;
} }
@ -41,7 +41,7 @@ impl View {
let mut new_delta = None; let mut new_delta = None;
for ext in &self.delete_exts { for ext in &self.delete_exts {
if let Some(delta) = ext.apply(delta, interval) { if let Some(delta) = ext.apply(delta, interval) {
log::debug!("[{}]: applied, delta: {}", ext.ext_name(), delta); log::trace!("[{}]: applied, delta: {}", ext.ext_name(), delta);
new_delta = Some(delta); new_delta = Some(delta);
break; break;
} }
@ -57,7 +57,7 @@ impl View {
let mut new_delta = None; let mut new_delta = None;
for ext in &self.format_exts { for ext in &self.format_exts {
if let Some(delta) = ext.apply(delta, interval, &attribute) { if let Some(delta) = ext.apply(delta, interval, &attribute) {
log::debug!("[{}]: applied, delta: {}", ext.ext_name(), delta); log::trace!("[{}]: applied, delta: {}", ext.ext_name(), delta);
new_delta = Some(delta); new_delta = Some(delta);
break; break;
} }

View file

@ -252,7 +252,7 @@ impl Delta {
}, },
(Some(Operation::Retain(retain)), Some(Operation::Retain(o_retain))) => { (Some(Operation::Retain(retain)), Some(Operation::Retain(o_retain))) => {
let composed_attrs = compose_operation(&next_op1, &next_op2); let composed_attrs = compose_operation(&next_op1, &next_op2);
log::debug!("[retain:{} - retain:{}]: {:?}", retain.n, o_retain.n, composed_attrs); log::trace!("[retain:{} - retain:{}]: {:?}", retain.n, o_retain.n, composed_attrs);
match retain.cmp(&o_retain) { match retain.cmp(&o_retain) {
Ordering::Less => { Ordering::Less => {
new_delta.retain(retain.n, composed_attrs); new_delta.retain(retain.n, composed_attrs);
@ -299,7 +299,7 @@ impl Delta {
let mut composed_attrs = compose_operation(&next_op1, &next_op2); let mut composed_attrs = compose_operation(&next_op1, &next_op2);
composed_attrs.remove_empty(); composed_attrs.remove_empty();
log::debug!("compose: [{} - {}], composed_attrs: {}", insert, o_retain, composed_attrs); log::trace!("compose: [{} - {}], composed_attrs: {}", insert, o_retain, composed_attrs);
match (insert.num_chars()).cmp(o_retain) { match (insert.num_chars()).cmp(o_retain) {
Ordering::Less => { Ordering::Less => {
new_delta.insert(&insert.s, composed_attrs.clone()); new_delta.insert(&insert.s, composed_attrs.clone());
@ -533,9 +533,9 @@ impl Delta {
if other.is_empty() { if other.is_empty() {
return inverted; return inverted;
} }
log::debug!("🌜Calculate invert delta"); log::trace!("🌜Calculate invert delta");
log::debug!("current: {}", self); log::trace!("current: {}", self);
log::debug!("other: {}", other); log::trace!("other: {}", other);
let mut index = 0; let mut index = 0;
for op in &self.ops { for op in &self.ops {
let len: usize = op.len() as usize; let len: usize = op.len() as usize;
@ -548,20 +548,20 @@ impl Delta {
match op.has_attribute() { match op.has_attribute() {
true => invert_from_other(&mut inverted, other, op, index, index + len), true => invert_from_other(&mut inverted, other, op, index, index + len),
false => { false => {
log::debug!("invert retain: {} by retain {} {}", op, len, op.get_attributes()); log::trace!("invert retain: {} by retain {} {}", op, len, op.get_attributes());
inverted.retain(len as usize, op.get_attributes()) inverted.retain(len as usize, op.get_attributes())
}, },
} }
index += len; index += len;
}, },
Operation::Insert(_) => { Operation::Insert(_) => {
log::debug!("invert insert: {} by delete {}", op, len); log::trace!("invert insert: {} by delete {}", op, len);
inverted.delete(len as usize); inverted.delete(len as usize);
}, },
} }
} }
log::debug!("🌛invert result: {}", inverted); log::trace!("🌛invert result: {}", inverted);
inverted inverted
} }
@ -581,22 +581,22 @@ impl Delta {
} }
fn invert_from_other(base: &mut Delta, other: &Delta, operation: &Operation, start: usize, end: usize) { fn invert_from_other(base: &mut Delta, other: &Delta, operation: &Operation, start: usize, end: usize) {
log::debug!("invert op: {} [{}:{}]", operation, start, end); log::trace!("invert op: {} [{}:{}]", operation, start, end);
let other_ops = DeltaIter::from_interval(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 { other_ops.into_iter().for_each(|other_op| match operation {
Operation::Delete(n) => { Operation::Delete(n) => {
log::debug!("invert delete: {} by add {}", n, other_op); log::trace!("invert delete: {} by add {}", n, other_op);
base.add(other_op); base.add(other_op);
}, },
Operation::Retain(retain) => { Operation::Retain(retain) => {
log::debug!( log::trace!(
"invert attributes: {:?}, {:?}", "invert attributes: {:?}, {:?}",
operation.get_attributes(), operation.get_attributes(),
other_op.get_attributes() other_op.get_attributes()
); );
let inverted_attrs = invert_attributes(operation.get_attributes(), other_op.get_attributes()); let inverted_attrs = invert_attributes(operation.get_attributes(), other_op.get_attributes());
log::debug!("invert attributes result: {:?}", inverted_attrs); log::trace!("invert attributes result: {:?}", inverted_attrs);
log::debug!("invert retain: {} by retain len: {}, {}", retain, other_op.len(), inverted_attrs); log::trace!("invert retain: {} by retain len: {}, {}", retain, other_op.len(), inverted_attrs);
base.retain(other_op.len(), inverted_attrs); base.retain(other_op.len(), inverted_attrs);
}, },
Operation::Insert(_) => { Operation::Insert(_) => {

View file

@ -154,13 +154,13 @@ impl<'a> Iterator for AttributesIter<'a> {
match next_op.unwrap() { match next_op.unwrap() {
Operation::Delete(_n) => {}, Operation::Delete(_n) => {},
Operation::Retain(retain) => { Operation::Retain(retain) => {
log::debug!("extend retain attributes with {} ", &retain.attributes); log::trace!("extend retain attributes with {} ", &retain.attributes);
attributes.extend(retain.attributes.clone()); attributes.extend(retain.attributes.clone());
length = retain.n; length = retain.n;
}, },
Operation::Insert(insert) => { Operation::Insert(insert) => {
log::debug!("extend insert attributes with {} ", &insert.attributes); log::trace!("extend insert attributes with {} ", &insert.attributes);
attributes.extend(insert.attributes.clone()); attributes.extend(insert.attributes.clone());
length = insert.num_chars(); length = insert.num_chars();
}, },

View file

@ -161,7 +161,7 @@ impl fmt::Display for Retain {
impl Retain { impl Retain {
pub fn merge_or_new(&mut self, n: usize, attributes: Attributes) -> Option<Operation> { pub fn merge_or_new(&mut self, n: usize, attributes: Attributes) -> Option<Operation> {
log::debug!("merge_retain_or_new_op: len: {:?}, l: {} - r: {}", n, self.attributes, attributes); log::trace!("merge_retain_or_new_op: len: {:?}, l: {} - r: {}", n, self.attributes, attributes);
if self.attributes == attributes { if self.attributes == attributes {
self.n += n; self.n += n;

View file

@ -490,11 +490,11 @@ fn delta_transform_test() {
let (a_prime, b_prime) = a.transform(&b).unwrap(); let (a_prime, b_prime) = a.transform(&b).unwrap();
assert_eq!( assert_eq!(
r#"[{"insert":"123","attributes":{"bold":"true"}},{"retain":3}]"#, r#"[{"insert":"123","attributes":{"bold":true}},{"retain":3}]"#,
serde_json::to_string(&a_prime).unwrap() serde_json::to_string(&a_prime).unwrap()
); );
assert_eq!( assert_eq!(
r#"[{"retain":3,"attributes":{"bold":"true"}},{"insert":"456"}]"#, r#"[{"retain":3,"attributes":{"bold":true}},{"insert":"456"}]"#,
serde_json::to_string(&b_prime).unwrap() serde_json::to_string(&b_prime).unwrap()
); );
} }

View file

@ -82,10 +82,10 @@ fn delta_deserialize_test() {
#[test] #[test]
fn delta_deserialize_null_test() { fn delta_deserialize_null_test() {
let json = r#"[ let json = r#"[
{"retain":2,"attributes":{"italic":null}} {"retain":7,"attributes":{"bold":null}}
]"#; ]"#;
let delta = Delta::from_json(json).unwrap(); let delta = Delta::from_json(json).unwrap();
eprintln!("{}", delta); println!("{}", delta);
} }
#[test] #[test]

View file

@ -40,6 +40,7 @@ fn crate_log_filter(level: Option<String>) -> String {
filters.push(format!("flowy_user={}", level)); filters.push(format!("flowy_user={}", level));
filters.push(format!("flowy_document={}", level)); filters.push(format!("flowy_document={}", level));
filters.push(format!("flowy_observable={}", level)); filters.push(format!("flowy_observable={}", level));
filters.push(format!("flowy_ot={}", level));
filters.push(format!("info")); filters.push(format!("info"));
filters.join(",") filters.join(",")
} }

View file

@ -1,16 +1,12 @@
use flowy_ot::core::Delta; use flowy_ot::core::Delta;
#[derive(Debug)] #[derive(Debug)]
pub struct DeltaData(pub Delta); pub struct DeltaData(pub Vec<u8>);
impl DeltaData { impl DeltaData {
pub fn parse(data: Vec<u8>) -> Result<DeltaData, String> { pub fn parse(data: Vec<u8>) -> Result<DeltaData, String> {
let delta = Delta::from_bytes(data).map_err(|e| format!("{:?}", e))?; // let _ = Delta::from_bytes(data.clone()).map_err(|e| format!("{:?}", e))?;
Ok(Self(delta)) Ok(Self(data))
} }
} }
impl AsRef<Delta> for DeltaData {
fn as_ref(&self) -> &Delta { &self.0 }
}

View file

@ -130,8 +130,7 @@ impl TryInto<SaveDocParams> for SaveViewDataRequest {
// Opti: Vec<u8> -> Delta -> Vec<u8> // Opti: Vec<u8> -> Delta -> Vec<u8>
let data = DeltaData::parse(self.data) let data = DeltaData::parse(self.data)
.map_err(|e| ErrorBuilder::new(ErrorCode::ViewDataInvalid).msg(e).build())? .map_err(|e| ErrorBuilder::new(ErrorCode::ViewDataInvalid).msg(e).build())?
.0 .0;
.into_bytes();
Ok(SaveDocParams { id: view_id, data }) Ok(SaveDocParams { id: view_id, data })
} }
@ -157,8 +156,7 @@ impl TryInto<ApplyChangesetParams> for ApplyChangesetRequest {
// Opti: Vec<u8> -> Delta -> Vec<u8> // Opti: Vec<u8> -> Delta -> Vec<u8>
let data = DeltaData::parse(self.data) let data = DeltaData::parse(self.data)
.map_err(|e| ErrorBuilder::new(ErrorCode::ViewDataInvalid).msg(e).build())? .map_err(|e| ErrorBuilder::new(ErrorCode::ViewDataInvalid).msg(e).build())?
.0 .0;
.into_bytes();
Ok(ApplyChangesetParams { id: view_id, data }) Ok(ApplyChangesetParams { id: view_id, data })
} }

View file

@ -52,6 +52,6 @@ pub enum WorkspaceEvent {
#[event(input = "SaveViewDataRequest")] #[event(input = "SaveViewDataRequest")]
SaveViewData = 206, SaveViewData = 206,
#[event(input = "ApplyChangesetRequest")] #[event(input = "ApplyChangesetRequest", output = "Doc")]
ApplyChangeset = 207, ApplyChangeset = 207,
} }

View file

@ -69,10 +69,10 @@ pub(crate) async fn update_view_data_handler(
pub(crate) async fn apply_changeset_handler( pub(crate) async fn apply_changeset_handler(
data: Data<ApplyChangesetRequest>, data: Data<ApplyChangesetRequest>,
controller: Unit<Arc<ViewController>>, controller: Unit<Arc<ViewController>>,
) -> Result<(), WorkspaceError> { ) -> DataResult<Doc, WorkspaceError> {
let params: ApplyChangesetParams = data.into_inner().try_into()?; let params: ApplyChangesetParams = data.into_inner().try_into()?;
let _ = controller.apply_changeset(params).await?; let doc = controller.apply_changeset(params).await?;
Ok(()) data_result(doc)
} }
#[tracing::instrument(skip(data, controller), err)] #[tracing::instrument(skip(data, controller), err)]

View file

@ -129,9 +129,9 @@ impl ViewController {
Ok(()) Ok(())
} }
pub(crate) async fn apply_changeset(&self, params: ApplyChangesetParams) -> Result<(), WorkspaceError> { pub(crate) async fn apply_changeset(&self, params: ApplyChangesetParams) -> Result<Doc, WorkspaceError> {
let _ = self.document.apply_changeset(params).await?; let doc = self.document.apply_changeset(params).await?;
Ok(()) Ok(doc)
} }
} }