remove notify from edit context

This commit is contained in:
appflowy 2021-09-26 16:39:57 +08:00
parent 9175efa4c6
commit 77313ab431
51 changed files with 1120 additions and 715 deletions

View File

@ -30,8 +30,8 @@ class DocBloc extends Bloc<DocEvent, DocState> {
(doc) {
final flowyDoc = FlowyDoc(
doc: doc,
data: _decodeToDocument(
Uint8List.fromList(doc.data),
data: _decodeJsonToDocument(
doc.data,
),
iDocImpl: iDocImpl);
return DocState.loadDoc(flowyDoc);
@ -42,11 +42,17 @@ class DocBloc extends Bloc<DocEvent, DocState> {
);
}
Document _decodeToDocument(Uint8List data) {
Document _decodeListToDocument(Uint8List data) {
final json = jsonDecode(utf8.decode(data));
final document = Document.fromJson(json);
return document;
}
Document _decodeJsonToDocument(String data) {
final json = jsonDecode(data);
final document = Document.fromJson(json);
return document;
}
}
@freezed

View File

@ -26,7 +26,7 @@ class FlowyDoc implements EditorDeltaSender {
result.fold((rustDoc) {
// final json = utf8.decode(doc.data);
final rustDelta = Delta.fromJson(jsonDecode(utf8.decode(rustDoc.data)));
final rustDelta = Delta.fromJson(jsonDecode(rustDoc.data));
if (delta != rustDelta) {
Log.error("Receive : $rustDelta");
@ -41,6 +41,6 @@ class FlowyDoc implements EditorDeltaSender {
abstract class IDoc {
Future<Either<Doc, WorkspaceError>> readDoc();
Future<Either<Doc, WorkspaceError>> applyChangeset({String? json});
Future<Either<Doc, WorkspaceError>> applyChangeset({required String json});
Future<Either<Unit, WorkspaceError>> closeDoc();
}

View File

@ -24,12 +24,13 @@ class IDocImpl extends IDoc {
}
@override
Future<Either<Doc, WorkspaceError>> applyChangeset({String? json}) {
return repo.applyChangeset(data: _encodeText(json));
Future<Either<Doc, WorkspaceError>> applyChangeset({required String json}) {
return repo.applyDelta(data: json);
}
}
Uint8List _encodeText(String? json) {
// ignore: unused_element
Uint8List _encodeJsonText(String? json) {
final data = utf8.encode(json ?? "");
return Uint8List.fromList(data);
}

View File

@ -18,8 +18,7 @@ class DocRepository {
return WorkspaceEventOpenView(request).send();
}
Future<Either<Doc, WorkspaceError>> applyChangeset(
{required Uint8List data}) {
Future<Either<Doc, WorkspaceError>> applyDelta({required String data}) {
final request = DocDelta.create()
..docId = docId
..data = data;

View File

@ -13,14 +13,14 @@ import 'package:protobuf/protobuf.dart' as $pb;
class CreateDocParams extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateDocParams', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY)
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
..hasRequiredFields = false
;
CreateDocParams._() : super();
factory CreateDocParams({
$core.String? id,
$core.List<$core.int>? data,
$core.String? data,
}) {
final _result = create();
if (id != null) {
@ -62,9 +62,9 @@ class CreateDocParams extends $pb.GeneratedMessage {
void clearId() => clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get data => $_getN(1);
$core.String get data => $_getSZ(1);
@$pb.TagNumber(2)
set data($core.List<$core.int> v) { $_setBytes(1, v); }
set data($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasData() => $_has(1);
@$pb.TagNumber(2)
@ -74,7 +74,7 @@ class CreateDocParams extends $pb.GeneratedMessage {
class Doc extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Doc', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY)
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'revId')
..hasRequiredFields = false
;
@ -82,7 +82,7 @@ class Doc extends $pb.GeneratedMessage {
Doc._() : super();
factory Doc({
$core.String? id,
$core.List<$core.int>? data,
$core.String? data,
$fixnum.Int64? revId,
}) {
final _result = create();
@ -128,9 +128,9 @@ class Doc extends $pb.GeneratedMessage {
void clearId() => clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get data => $_getN(1);
$core.String get data => $_getSZ(1);
@$pb.TagNumber(2)
set data($core.List<$core.int> v) { $_setBytes(1, v); }
set data($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasData() => $_has(1);
@$pb.TagNumber(2)
@ -149,7 +149,7 @@ class Doc extends $pb.GeneratedMessage {
class UpdateDocParams extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UpdateDocParams', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId')
..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY)
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'revId')
..hasRequiredFields = false
;
@ -157,7 +157,7 @@ class UpdateDocParams extends $pb.GeneratedMessage {
UpdateDocParams._() : super();
factory UpdateDocParams({
$core.String? docId,
$core.List<$core.int>? data,
$core.String? data,
$fixnum.Int64? revId,
}) {
final _result = create();
@ -203,9 +203,9 @@ class UpdateDocParams extends $pb.GeneratedMessage {
void clearDocId() => clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get data => $_getN(1);
$core.String get data => $_getSZ(1);
@$pb.TagNumber(2)
set data($core.List<$core.int> v) { $_setBytes(1, v); }
set data($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasData() => $_has(1);
@$pb.TagNumber(2)
@ -224,14 +224,14 @@ class UpdateDocParams extends $pb.GeneratedMessage {
class DocDelta extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocDelta', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId')
..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY)
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
..hasRequiredFields = false
;
DocDelta._() : super();
factory DocDelta({
$core.String? docId,
$core.List<$core.int>? data,
$core.String? data,
}) {
final _result = create();
if (docId != null) {
@ -273,9 +273,9 @@ class DocDelta extends $pb.GeneratedMessage {
void clearDocId() => clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get data => $_getN(1);
$core.String get data => $_getSZ(1);
@$pb.TagNumber(2)
set data($core.List<$core.int> v) { $_setBytes(1, v); }
set data($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasData() => $_has(1);
@$pb.TagNumber(2)

View File

@ -13,47 +13,47 @@ const CreateDocParams$json = const {
'1': 'CreateDocParams',
'2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
const {'1': 'data', '3': 2, '4': 1, '5': 12, '10': 'data'},
const {'1': 'data', '3': 2, '4': 1, '5': 9, '10': 'data'},
],
};
/// Descriptor for `CreateDocParams`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List createDocParamsDescriptor = $convert.base64Decode('Cg9DcmVhdGVEb2NQYXJhbXMSDgoCaWQYASABKAlSAmlkEhIKBGRhdGEYAiABKAxSBGRhdGE=');
final $typed_data.Uint8List createDocParamsDescriptor = $convert.base64Decode('Cg9DcmVhdGVEb2NQYXJhbXMSDgoCaWQYASABKAlSAmlkEhIKBGRhdGEYAiABKAlSBGRhdGE=');
@$core.Deprecated('Use docDescriptor instead')
const Doc$json = const {
'1': 'Doc',
'2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
const {'1': 'data', '3': 2, '4': 1, '5': 12, '10': 'data'},
const {'1': 'data', '3': 2, '4': 1, '5': 9, '10': 'data'},
const {'1': 'rev_id', '3': 3, '4': 1, '5': 3, '10': 'revId'},
],
};
/// Descriptor for `Doc`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List docDescriptor = $convert.base64Decode('CgNEb2MSDgoCaWQYASABKAlSAmlkEhIKBGRhdGEYAiABKAxSBGRhdGESFQoGcmV2X2lkGAMgASgDUgVyZXZJZA==');
final $typed_data.Uint8List docDescriptor = $convert.base64Decode('CgNEb2MSDgoCaWQYASABKAlSAmlkEhIKBGRhdGEYAiABKAlSBGRhdGESFQoGcmV2X2lkGAMgASgDUgVyZXZJZA==');
@$core.Deprecated('Use updateDocParamsDescriptor instead')
const UpdateDocParams$json = const {
'1': 'UpdateDocParams',
'2': const [
const {'1': 'doc_id', '3': 1, '4': 1, '5': 9, '10': 'docId'},
const {'1': 'data', '3': 2, '4': 1, '5': 12, '10': 'data'},
const {'1': 'data', '3': 2, '4': 1, '5': 9, '10': 'data'},
const {'1': 'rev_id', '3': 3, '4': 1, '5': 3, '10': 'revId'},
],
};
/// Descriptor for `UpdateDocParams`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List updateDocParamsDescriptor = $convert.base64Decode('Cg9VcGRhdGVEb2NQYXJhbXMSFQoGZG9jX2lkGAEgASgJUgVkb2NJZBISCgRkYXRhGAIgASgMUgRkYXRhEhUKBnJldl9pZBgDIAEoA1IFcmV2SWQ=');
final $typed_data.Uint8List updateDocParamsDescriptor = $convert.base64Decode('Cg9VcGRhdGVEb2NQYXJhbXMSFQoGZG9jX2lkGAEgASgJUgVkb2NJZBISCgRkYXRhGAIgASgJUgRkYXRhEhUKBnJldl9pZBgDIAEoA1IFcmV2SWQ=');
@$core.Deprecated('Use docDeltaDescriptor instead')
const DocDelta$json = const {
'1': 'DocDelta',
'2': const [
const {'1': 'doc_id', '3': 1, '4': 1, '5': 9, '10': 'docId'},
const {'1': 'data', '3': 2, '4': 1, '5': 12, '10': 'data'},
const {'1': 'data', '3': 2, '4': 1, '5': 9, '10': 'data'},
],
};
/// Descriptor for `DocDelta`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List docDeltaDescriptor = $convert.base64Decode('CghEb2NEZWx0YRIVCgZkb2NfaWQYASABKAlSBWRvY0lkEhIKBGRhdGEYAiABKAxSBGRhdGE=');
final $typed_data.Uint8List docDeltaDescriptor = $convert.base64Decode('CghEb2NEZWx0YRIVCgZkb2NfaWQYASABKAlSBWRvY0lkEhIKBGRhdGEYAiABKAlSBGRhdGE=');
@$core.Deprecated('Use queryDocParamsDescriptor instead')
const QueryDocParams$json = const {
'1': 'QueryDocParams',

View File

@ -10,6 +10,10 @@ import 'dart:core' as $core;
import 'package:fixnum/fixnum.dart' as $fixnum;
import 'package:protobuf/protobuf.dart' as $pb;
import 'revision.pbenum.dart';
export 'revision.pbenum.dart';
class Revision extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Revision', createEmptyInstance: create)
..aInt64(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'baseRevId')
@ -17,6 +21,7 @@ class Revision extends $pb.GeneratedMessage {
..a<$core.List<$core.int>>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'delta', $pb.PbFieldType.OY)
..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'md5')
..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId')
..e<RevType>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ty', $pb.PbFieldType.OE, defaultOrMaker: RevType.Local, valueOf: RevType.valueOf, enumValues: RevType.values)
..hasRequiredFields = false
;
@ -27,6 +32,7 @@ class Revision extends $pb.GeneratedMessage {
$core.List<$core.int>? delta,
$core.String? md5,
$core.String? docId,
RevType? ty,
}) {
final _result = create();
if (baseRevId != null) {
@ -44,6 +50,9 @@ class Revision extends $pb.GeneratedMessage {
if (docId != null) {
_result.docId = docId;
}
if (ty != null) {
_result.ty = ty;
}
return _result;
}
factory Revision.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@ -111,5 +120,14 @@ class Revision extends $pb.GeneratedMessage {
$core.bool hasDocId() => $_has(4);
@$pb.TagNumber(5)
void clearDocId() => clearField(5);
@$pb.TagNumber(6)
RevType get ty => $_getN(5);
@$pb.TagNumber(6)
set ty(RevType v) { setField(6, v); }
@$pb.TagNumber(6)
$core.bool hasTy() => $_has(5);
@$pb.TagNumber(6)
void clearTy() => clearField(6);
}

View File

@ -5,3 +5,22 @@
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
// ignore_for_file: UNDEFINED_SHOWN_NAME
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class RevType extends $pb.ProtobufEnum {
static const RevType Local = RevType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Local');
static const RevType Remote = RevType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Remote');
static const $core.List<RevType> values = <RevType> [
Local,
Remote,
];
static final $core.Map<$core.int, RevType> _byValue = $pb.ProtobufEnum.initByValue(values);
static RevType? valueOf($core.int value) => _byValue[value];
const RevType._($core.int v, $core.String n) : super(v, n);
}

View File

@ -8,6 +8,17 @@
import 'dart:core' as $core;
import 'dart:convert' as $convert;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use revTypeDescriptor instead')
const RevType$json = const {
'1': 'RevType',
'2': const [
const {'1': 'Local', '2': 0},
const {'1': 'Remote', '2': 1},
],
};
/// Descriptor for `RevType`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List revTypeDescriptor = $convert.base64Decode('CgdSZXZUeXBlEgkKBUxvY2FsEAASCgoGUmVtb3RlEAE=');
@$core.Deprecated('Use revisionDescriptor instead')
const Revision$json = const {
'1': 'Revision',
@ -17,8 +28,9 @@ const Revision$json = const {
const {'1': 'delta', '3': 3, '4': 1, '5': 12, '10': 'delta'},
const {'1': 'md5', '3': 4, '4': 1, '5': 9, '10': 'md5'},
const {'1': 'doc_id', '3': 5, '4': 1, '5': 9, '10': 'docId'},
const {'1': 'ty', '3': 6, '4': 1, '5': 14, '6': '.RevType', '10': 'ty'},
],
};
/// Descriptor for `Revision`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List revisionDescriptor = $convert.base64Decode('CghSZXZpc2lvbhIeCgtiYXNlX3Jldl9pZBgBIAEoA1IJYmFzZVJldklkEhUKBnJldl9pZBgCIAEoA1IFcmV2SWQSFAoFZGVsdGEYAyABKAxSBWRlbHRhEhAKA21kNRgEIAEoCVIDbWQ1EhUKBmRvY19pZBgFIAEoCVIFZG9jSWQ=');
final $typed_data.Uint8List revisionDescriptor = $convert.base64Decode('CghSZXZpc2lvbhIeCgtiYXNlX3Jldl9pZBgBIAEoA1IJYmFzZVJldklkEhUKBnJldl9pZBgCIAEoA1IFcmV2SWQSFAoFZGVsdGEYAyABKAxSBWRlbHRhEhAKA21kNRgEIAEoCVIDbWQ1EhUKBmRvY19pZBgFIAEoCVIFZG9jSWQSGAoCdHkYBiABKA4yCC5SZXZUeXBlUgJ0eQ==');

View File

@ -137,7 +137,7 @@ class CreateViewParams extends $pb.GeneratedMessage {
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail')
..e<ViewType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.Blank, valueOf: ViewType.valueOf, enumValues: ViewType.values)
..a<$core.List<$core.int>>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY)
..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
..hasRequiredFields = false
;
@ -148,7 +148,7 @@ class CreateViewParams extends $pb.GeneratedMessage {
$core.String? desc,
$core.String? thumbnail,
ViewType? viewType,
$core.List<$core.int>? data,
$core.String? data,
}) {
final _result = create();
if (belongToId != null) {
@ -238,9 +238,9 @@ class CreateViewParams extends $pb.GeneratedMessage {
void clearViewType() => clearField(5);
@$pb.TagNumber(6)
$core.List<$core.int> get data => $_getN(5);
$core.String get data => $_getSZ(5);
@$pb.TagNumber(6)
set data($core.List<$core.int> v) { $_setBytes(5, v); }
set data($core.String v) { $_setString(5, v); }
@$pb.TagNumber(6)
$core.bool hasData() => $_has(5);
@$pb.TagNumber(6)

View File

@ -45,12 +45,12 @@ const CreateViewParams$json = const {
const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'},
const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '10': 'thumbnail'},
const {'1': 'view_type', '3': 5, '4': 1, '5': 14, '6': '.ViewType', '10': 'viewType'},
const {'1': 'data', '3': 6, '4': 1, '5': 12, '10': 'data'},
const {'1': 'data', '3': 6, '4': 1, '5': 9, '10': 'data'},
],
};
/// Descriptor for `CreateViewParams`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSJgoJdmlld190eXBlGAUgASgOMgkuVmlld1R5cGVSCHZpZXdUeXBlEhIKBGRhdGEYBiABKAxSBGRhdGE=');
final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSJgoJdmlld190eXBlGAUgASgOMgkuVmlld1R5cGVSCHZpZXdUeXBlEhIKBGRhdGEYBiABKAlSBGRhdGE=');
@$core.Deprecated('Use viewDescriptor instead')
const View$json = const {
'1': 'View',

View File

@ -319,15 +319,15 @@ class UpdateViewParams extends $pb.GeneratedMessage {
void clearIsTrash() => clearField(5);
}
class ApplyChangesetRequest extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ApplyChangesetRequest', createEmptyInstance: create)
class DocDeltaRequest extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocDeltaRequest', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId')
..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY)
..hasRequiredFields = false
;
ApplyChangesetRequest._() : super();
factory ApplyChangesetRequest({
DocDeltaRequest._() : super();
factory DocDeltaRequest({
$core.String? viewId,
$core.List<$core.int>? data,
}) {
@ -340,26 +340,26 @@ class ApplyChangesetRequest extends $pb.GeneratedMessage {
}
return _result;
}
factory ApplyChangesetRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory ApplyChangesetRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
factory DocDeltaRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory DocDeltaRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
ApplyChangesetRequest clone() => ApplyChangesetRequest()..mergeFromMessage(this);
DocDeltaRequest clone() => DocDeltaRequest()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
ApplyChangesetRequest copyWith(void Function(ApplyChangesetRequest) updates) => super.copyWith((message) => updates(message as ApplyChangesetRequest)) as ApplyChangesetRequest; // ignore: deprecated_member_use
DocDeltaRequest copyWith(void Function(DocDeltaRequest) updates) => super.copyWith((message) => updates(message as DocDeltaRequest)) as DocDeltaRequest; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ApplyChangesetRequest create() => ApplyChangesetRequest._();
ApplyChangesetRequest createEmptyInstance() => create();
static $pb.PbList<ApplyChangesetRequest> createRepeated() => $pb.PbList<ApplyChangesetRequest>();
static DocDeltaRequest create() => DocDeltaRequest._();
DocDeltaRequest createEmptyInstance() => create();
static $pb.PbList<DocDeltaRequest> createRepeated() => $pb.PbList<DocDeltaRequest>();
@$core.pragma('dart2js:noInline')
static ApplyChangesetRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ApplyChangesetRequest>(create);
static ApplyChangesetRequest? _defaultInstance;
static DocDeltaRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DocDeltaRequest>(create);
static DocDeltaRequest? _defaultInstance;
@$pb.TagNumber(1)
$core.String get viewId => $_getSZ(0);

View File

@ -48,14 +48,14 @@ const UpdateViewParams$json = const {
/// Descriptor for `UpdateViewParams`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List updateViewParamsDescriptor = $convert.base64Decode('ChBVcGRhdGVWaWV3UGFyYW1zEhcKB3ZpZXdfaWQYASABKAlSBnZpZXdJZBIUCgRuYW1lGAIgASgJSABSBG5hbWUSFAoEZGVzYxgDIAEoCUgBUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgCUgl0aHVtYm5haWwSGwoIaXNfdHJhc2gYBSABKAhIA1IHaXNUcmFzaEINCgtvbmVfb2ZfbmFtZUINCgtvbmVfb2ZfZGVzY0ISChBvbmVfb2ZfdGh1bWJuYWlsQhEKD29uZV9vZl9pc190cmFzaA==');
@$core.Deprecated('Use applyChangesetRequestDescriptor instead')
const ApplyChangesetRequest$json = const {
'1': 'ApplyChangesetRequest',
@$core.Deprecated('Use docDeltaRequestDescriptor instead')
const DocDeltaRequest$json = const {
'1': 'DocDeltaRequest',
'2': const [
const {'1': 'view_id', '3': 1, '4': 1, '5': 9, '10': 'viewId'},
const {'1': 'data', '3': 2, '4': 1, '5': 12, '10': 'data'},
],
};
/// Descriptor for `ApplyChangesetRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List applyChangesetRequestDescriptor = $convert.base64Decode('ChVBcHBseUNoYW5nZXNldFJlcXVlc3QSFwoHdmlld19pZBgBIAEoCVIGdmlld0lkEhIKBGRhdGEYAiABKAxSBGRhdGE=');
/// Descriptor for `DocDeltaRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List docDeltaRequestDescriptor = $convert.base64Decode('Cg9Eb2NEZWx0YVJlcXVlc3QSFwoHdmlld19pZBgBIAEoCVIGdmlld0lkEhIKBGRhdGEYAiABKAxSBGRhdGE=');

View File

@ -2,6 +2,7 @@
CREATE TABLE IF NOT EXISTS doc_table(
id uuid NOT NULL,
PRIMARY KEY (id),
data bytea NOT NULL DEFAULT '',
-- data bytea NOT NULL DEFAULT '',
data TEXT NOT NULL DEFAULT '',
rev_id bigint NOT NULL DEFAULT 0
);

View File

@ -1,5 +1,5 @@
# https://rust-lang.github.io/rustfmt/?version=master&search=
max_width = 100
max_width = 120
tab_spaces = 4
fn_single_line = true
match_block_trailing_comma = true

View File

@ -5,7 +5,7 @@ pub(crate) const DOC_TABLE: &'static str = "doc_table";
#[derive(Debug, Clone, sqlx::FromRow)]
pub struct DocTable {
pub(crate) id: uuid::Uuid,
pub(crate) data: Vec<u8>,
pub(crate) data: String,
pub(crate) rev_id: i64,
}

View File

@ -4,11 +4,11 @@ use crate::service::{
ws::{entities::Socket, WsMessageAdaptor},
};
use actix_web::web::Data;
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
use byteorder::{BigEndian, WriteBytesExt};
use bytes::Bytes;
use flowy_document::{
entities::ws::{WsDataType, WsDocumentData},
protobuf::{Doc, Revision, UpdateDocParams},
protobuf::{Doc, RevType, Revision, UpdateDocParams},
services::doc::Document,
};
use flowy_net::errors::{internal_error, ServerError};
@ -31,7 +31,7 @@ pub(crate) struct EditDocContext {
impl EditDocContext {
pub(crate) fn new(doc: Doc, pg_pool: Data<PgPool>) -> Result<Self, ServerError> {
let delta = Delta::from_bytes(doc.data).map_err(internal_error)?;
let delta = Delta::from_bytes(&doc.data).map_err(internal_error)?;
let document = Arc::new(RwLock::new(Document::from_delta(delta)));
Ok(Self {
doc_id: doc.id.clone(),
@ -42,29 +42,25 @@ impl EditDocContext {
}
#[tracing::instrument(level = "debug", skip(self, socket, revision))]
pub(crate) async fn apply_revision(
&self,
socket: Socket,
revision: Revision,
) -> Result<(), ServerError> {
pub(crate) async fn apply_revision(&self, socket: Socket, revision: Revision) -> Result<(), ServerError> {
let _ = self.verify_md5(&revision)?;
if self.rev_id > revision.rev_id {
let (cli_prime, server_prime) = self.compose(revision.delta).map_err(internal_error)?;
let (cli_prime, server_prime) = self.compose(&revision.delta).map_err(internal_error)?;
let _ = self.update_document_delta(server_prime)?;
log::debug!("{} client delta: {}", self.doc_id, cli_prime.to_json());
let cli_revision = self.mk_revision(revision.rev_id, cli_prime);
let ws_cli_revision = mk_ws_rev_message(&self.doc_id, cli_revision);
let ws_cli_revision = mk_rev_ws_message(&self.doc_id, cli_revision);
socket.do_send(ws_cli_revision).map_err(internal_error)?;
Ok(())
} else {
let delta = Delta::from_bytes(revision.delta.clone()).map_err(internal_error)?;
let delta = Delta::from_bytes(&revision.delta).map_err(internal_error)?;
let _ = self.update_document_delta(delta)?;
socket.do_send(mk_ws_acked_message(&revision));
socket.do_send(mk_acked_ws_message(&revision));
// Opti: save with multiple revisions
let _ = self.save_doc_to_disk(&revision).await?;
let _ = self.save_revision(&revision).await?;
Ok(())
}
}
@ -78,23 +74,20 @@ impl EditDocContext {
delta: delta_data,
md5,
doc_id: self.doc_id.to_string(),
ty: RevType::Remote,
..Default::default()
};
revision
}
#[tracing::instrument(level = "debug", skip(self, delta_data))]
fn compose(&self, delta_data: Vec<u8>) -> Result<(Delta, Delta), OTError> {
log::debug!(
"{} document data: {}",
self.doc_id,
self.document.read().to_json()
);
fn compose(&self, delta_data: &Vec<u8>) -> Result<(Delta, Delta), OTError> {
log::debug!("{} document data: {}", self.doc_id, self.document.read().to_json());
let doc_delta = self.document.read().delta().clone();
let cli_delta = Delta::from_bytes(delta_data)?;
let (a, b) = doc_delta.transform(&cli_delta)?;
let (cli_prime, server_prime) = doc_delta.transform(&cli_delta)?;
Ok((a, b))
Ok((cli_prime, server_prime))
}
#[tracing::instrument(level = "debug", skip(self, delta))]
@ -105,9 +98,7 @@ impl EditDocContext {
log::error!("Failed to acquire write lock of document");
},
Some(mut write_guard) => {
let _ = write_guard
.apply_delta(delta.clone())
.map_err(internal_error)?;
let _ = write_guard.compose_delta(&delta).map_err(internal_error)?;
log::debug!("Document: {}", write_guard.to_plain_string());
},
@ -122,18 +113,20 @@ impl EditDocContext {
Ok(())
}
async fn save_doc_to_disk(&self, revision: &Revision) -> Result<(), ServerError> {
#[tracing::instrument(level = "debug", skip(self, revision))]
async fn save_revision(&self, revision: &Revision) -> Result<(), ServerError> {
let mut params = UpdateDocParams::new();
params.set_doc_id(self.doc_id.clone());
params.set_data(self.document.read().to_bytes());
params.set_data(self.document.read().to_json());
params.set_rev_id(revision.rev_id);
let _ = update_doc(self.pg_pool.get_ref(), params).await?;
Ok(())
}
}
fn mk_ws_rev_message(doc_id: &str, revision: Revision) -> WsMessageAdaptor {
fn mk_rev_ws_message(doc_id: &str, revision: Revision) -> WsMessageAdaptor {
let bytes = revision.write_to_bytes().unwrap();
let data = WsDocumentData {
@ -147,7 +140,7 @@ fn mk_ws_rev_message(doc_id: &str, revision: Revision) -> WsMessageAdaptor {
WsMessageAdaptor(bytes)
}
fn mk_ws_acked_message(revision: &Revision) -> WsMessageAdaptor {
fn mk_acked_ws_message(revision: &Revision) -> WsMessageAdaptor {
let mut wtr = vec![];
let _ = wtr.write_i64::<BigEndian>(revision.rev_id);

View File

@ -16,13 +16,13 @@ impl NewDocSqlBuilder {
pub fn new(id: Uuid) -> Self {
let table = DocTable {
id,
data: vec![],
data: "".to_owned(),
rev_id: 0,
};
Self { table }
}
pub fn data(mut self, data: Vec<u8>) -> Self {
pub fn data(mut self, data: String) -> Self {
self.table.data = data;
self
}

View File

@ -1,9 +1,3 @@
use flowy_net::errors::ServerError;
use flowy_workspace::{
entities::view::default_delta,
protobuf::{App, CreateViewParams, View, ViewType, Workspace},
};
use crate::{
service::{
app::sql_builder::NewAppSqlBuilder as AppBuilder,
@ -12,6 +6,11 @@ use crate::{
},
sqlx_ext::{map_sqlx_error, DBTransaction},
};
use flowy_net::errors::ServerError;
use flowy_workspace::{
entities::view::VIEW_DEFAULT_DATA,
protobuf::{App, CreateViewParams, View, ViewType, Workspace},
};
pub async fn create_default_workspace(
transaction: &mut DBTransaction<'_>,
@ -24,10 +23,7 @@ pub async fn create_default_workspace(
Ok(workspace)
}
async fn create_workspace(
transaction: &mut DBTransaction<'_>,
user_id: &str,
) -> Result<Workspace, ServerError> {
async fn create_workspace(transaction: &mut DBTransaction<'_>, user_id: &str) -> Result<Workspace, ServerError> {
let (sql, args, workspace) = WorkspaceBuilder::new(user_id.as_ref())
.name("DefaultWorkspace")
.desc("Workspace created by AppFlowy")
@ -66,7 +62,7 @@ async fn create_view(transaction: &mut DBTransaction<'_>, app: &App) -> Result<V
desc: "View created by AppFlowy".to_string(),
thumbnail: "123.png".to_string(),
view_type: ViewType::Doc,
data: default_delta(),
data: VIEW_DEFAULT_DATA.to_string(),
unknown_fields: Default::default(),
cached_size: Default::default(),
};

View File

@ -1,6 +1,7 @@
-- Your SQL goes here
CREATE TABLE doc_table (
id TEXT NOT NULL PRIMARY KEY,
data BLOB NOT NULL DEFAULT (x''),
-- data BLOB NOT NULL DEFAULT (x''),
data TEXT NOT NULL DEFAULT '',
revision BIGINT NOT NULL DEFAULT 0
);

View File

@ -1,9 +1,10 @@
-- Your SQL goes here
CREATE TABLE op_table (
CREATE TABLE rev_table (
doc_id TEXT NOT NULL PRIMARY KEY,
base_rev_id BIGINT NOT NULL DEFAULT 0,
rev_id BIGINT NOT NULL DEFAULT 0,
data BLOB NOT NULL DEFAULT (x''),
md5 TEXT NOT NULL DEFAULT '',
state INTEGER NOT NULL DEFAULT 0
state INTEGER NOT NULL DEFAULT 0,
ty INTEGER NOT NULL DEFAULT 0
);

View File

@ -112,13 +112,18 @@ macro_rules! impl_sql_binary_expression {
*const [u8]: diesel::deserialize::FromSql<diesel::sql_types::Binary, DB>,
{
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
let slice_ptr = <*const [u8] as diesel::deserialize::FromSql<diesel::sql_types::Binary, DB>>::from_sql(bytes)?;
let slice_ptr =
<*const [u8] as diesel::deserialize::FromSql<diesel::sql_types::Binary, DB>>::from_sql(bytes)?;
let bytes = unsafe { &*slice_ptr };
match $target::try_from(bytes) {
Ok(object) => Ok(object),
Err(e) => {
log::error!("{:?} deserialize from bytes fail. {:?}", std::any::type_name::<$target>(), e);
log::error!(
"{:?} deserialize from bytes fail. {:?}",
std::any::type_name::<$target>(),
e
);
panic!();
},
}
@ -130,28 +135,25 @@ macro_rules! impl_sql_binary_expression {
#[macro_export]
macro_rules! impl_sql_integer_expression {
($target:ident) => {
use diesel::{
deserialize,
deserialize::FromSql,
serialize,
serialize::{Output, ToSql},
};
use std::io::Write;
impl<DB> ToSql<Integer, DB> for $target
impl<DB> diesel::serialize::ToSql<Integer, DB> for $target
where
DB: diesel::backend::Backend,
i32: ToSql<Integer, DB>,
i32: diesel::serialize::ToSql<Integer, DB>,
{
fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result { (*self as i32).to_sql(out) }
fn to_sql<W: std::io::Write>(
&self,
out: &mut diesel::serialize::Output<W, DB>,
) -> diesel::serialize::Result {
(*self as i32).to_sql(out)
}
}
impl<DB> FromSql<Integer, DB> for $target
impl<DB> diesel::deserialize::FromSql<Integer, DB> for $target
where
DB: diesel::backend::Backend,
i32: FromSql<Integer, DB>,
i32: diesel::deserialize::FromSql<Integer, DB>,
{
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
let smaill_int = i32::from_sql(bytes)?;
Ok($target::from(smaill_int))
}

View File

@ -16,19 +16,20 @@ table! {
table! {
doc_table (id) {
id -> Text,
data -> Binary,
data -> Text,
revision -> BigInt,
}
}
table! {
op_table (doc_id) {
rev_table (doc_id) {
doc_id -> Text,
base_rev_id -> BigInt,
rev_id -> BigInt,
data -> Binary,
md5 -> Text,
state -> Integer,
ty -> Integer,
}
}
@ -72,7 +73,7 @@ table! {
allow_tables_to_appear_in_same_query!(
app_table,
doc_table,
op_table,
rev_table,
user_table,
view_table,
workspace_table,

View File

@ -41,7 +41,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
| "CurrentWorkspace"
| "UpdateViewRequest"
| "UpdateViewParams"
| "ApplyChangesetRequest"
| "DocDeltaRequest"
| "DeleteViewRequest"
| "DeleteViewParams"
| "QueryViewRequest"
@ -81,6 +81,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
| "ErrorCode"
| "WorkspaceObservable"
| "WsModule"
| "RevType"
| "WsDataType"
| "DocObservable"
| "FFIStatusCode"

View File

@ -6,11 +6,16 @@ pub struct CreateDocParams {
pub id: String,
#[pb(index = 2)]
pub data: Vec<u8>,
pub data: String,
}
impl CreateDocParams {
pub fn new(id: &str, data: Vec<u8>) -> Self { Self { id: id.to_owned(), data } }
pub fn new(id: &str, data: String) -> Self {
Self {
id: id.to_owned(),
data,
}
}
}
#[derive(ProtoBuf, Default, Debug, Clone, Eq, PartialEq)]
@ -19,7 +24,7 @@ pub struct Doc {
pub id: String,
#[pb(index = 2)]
pub data: Vec<u8>,
pub data: String,
#[pb(index = 3)]
pub rev_id: i64,
@ -31,7 +36,7 @@ pub struct UpdateDocParams {
pub doc_id: String,
#[pb(index = 2)]
pub data: Vec<u8>,
pub data: String,
#[pb(index = 3)]
pub rev_id: i64,
@ -43,7 +48,7 @@ pub struct DocDelta {
pub doc_id: String,
#[pb(index = 2)]
pub data: Vec<u8>, // Delta
pub data: String, // Delta
}
#[derive(ProtoBuf, Default, Debug, Clone)]

View File

@ -1,4 +1,14 @@
use flowy_derive::ProtoBuf;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
#[derive(Debug, ProtoBuf_Enum, Clone, Eq, PartialEq)]
pub enum RevType {
Local = 0,
Remote = 1,
}
impl std::default::Default for RevType {
fn default() -> Self { RevType::Local }
}
#[derive(Debug, Clone, Default, ProtoBuf)]
pub struct Revision {
@ -16,16 +26,20 @@ pub struct Revision {
#[pb(index = 5)]
pub doc_id: String,
#[pb(index = 6)]
pub ty: RevType,
}
impl Revision {
pub fn new(base_rev_id: i64, rev_id: i64, delta: Vec<u8>, md5: String, doc_id: String) -> Revision {
pub fn new(base_rev_id: i64, rev_id: i64, delta: Vec<u8>, md5: String, doc_id: String, ty: RevType) -> Revision {
Self {
base_rev_id,
rev_id,
delta,
md5,
doc_id,
ty,
}
}
}

View File

@ -27,7 +27,7 @@
pub struct CreateDocParams {
// message fields
pub id: ::std::string::String,
pub data: ::std::vec::Vec<u8>,
pub data: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
@ -70,10 +70,10 @@ impl CreateDocParams {
::std::mem::replace(&mut self.id, ::std::string::String::new())
}
// bytes data = 2;
// string data = 2;
pub fn get_data(&self) -> &[u8] {
pub fn get_data(&self) -> &str {
&self.data
}
pub fn clear_data(&mut self) {
@ -81,19 +81,19 @@ impl CreateDocParams {
}
// Param is passed by value, moved
pub fn set_data(&mut self, v: ::std::vec::Vec<u8>) {
pub fn set_data(&mut self, v: ::std::string::String) {
self.data = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_data(&mut self) -> &mut ::std::vec::Vec<u8> {
pub fn mut_data(&mut self) -> &mut ::std::string::String {
&mut self.data
}
// Take field
pub fn take_data(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.data, ::std::vec::Vec::new())
pub fn take_data(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.data, ::std::string::String::new())
}
}
@ -110,7 +110,7 @@ impl ::protobuf::Message for CreateDocParams {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
},
2 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?;
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@ -128,7 +128,7 @@ impl ::protobuf::Message for CreateDocParams {
my_size += ::protobuf::rt::string_size(1, &self.id);
}
if !self.data.is_empty() {
my_size += ::protobuf::rt::bytes_size(2, &self.data);
my_size += ::protobuf::rt::string_size(2, &self.data);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
@ -140,7 +140,7 @@ impl ::protobuf::Message for CreateDocParams {
os.write_string(1, &self.id)?;
}
if !self.data.is_empty() {
os.write_bytes(2, &self.data)?;
os.write_string(2, &self.data)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
@ -185,7 +185,7 @@ impl ::protobuf::Message for CreateDocParams {
|m: &CreateDocParams| { &m.id },
|m: &mut CreateDocParams| { &mut m.id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"data",
|m: &CreateDocParams| { &m.data },
|m: &mut CreateDocParams| { &mut m.data },
@ -228,7 +228,7 @@ impl ::protobuf::reflect::ProtobufValue for CreateDocParams {
pub struct Doc {
// message fields
pub id: ::std::string::String,
pub data: ::std::vec::Vec<u8>,
pub data: ::std::string::String,
pub rev_id: i64,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
@ -272,10 +272,10 @@ impl Doc {
::std::mem::replace(&mut self.id, ::std::string::String::new())
}
// bytes data = 2;
// string data = 2;
pub fn get_data(&self) -> &[u8] {
pub fn get_data(&self) -> &str {
&self.data
}
pub fn clear_data(&mut self) {
@ -283,19 +283,19 @@ impl Doc {
}
// Param is passed by value, moved
pub fn set_data(&mut self, v: ::std::vec::Vec<u8>) {
pub fn set_data(&mut self, v: ::std::string::String) {
self.data = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_data(&mut self) -> &mut ::std::vec::Vec<u8> {
pub fn mut_data(&mut self) -> &mut ::std::string::String {
&mut self.data
}
// Take field
pub fn take_data(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.data, ::std::vec::Vec::new())
pub fn take_data(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.data, ::std::string::String::new())
}
// int64 rev_id = 3;
@ -327,7 +327,7 @@ impl ::protobuf::Message for Doc {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
},
2 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?;
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
},
3 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
@ -352,7 +352,7 @@ impl ::protobuf::Message for Doc {
my_size += ::protobuf::rt::string_size(1, &self.id);
}
if !self.data.is_empty() {
my_size += ::protobuf::rt::bytes_size(2, &self.data);
my_size += ::protobuf::rt::string_size(2, &self.data);
}
if self.rev_id != 0 {
my_size += ::protobuf::rt::value_size(3, self.rev_id, ::protobuf::wire_format::WireTypeVarint);
@ -367,7 +367,7 @@ impl ::protobuf::Message for Doc {
os.write_string(1, &self.id)?;
}
if !self.data.is_empty() {
os.write_bytes(2, &self.data)?;
os.write_string(2, &self.data)?;
}
if self.rev_id != 0 {
os.write_int64(3, self.rev_id)?;
@ -415,7 +415,7 @@ impl ::protobuf::Message for Doc {
|m: &Doc| { &m.id },
|m: &mut Doc| { &mut m.id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"data",
|m: &Doc| { &m.data },
|m: &mut Doc| { &mut m.data },
@ -464,7 +464,7 @@ impl ::protobuf::reflect::ProtobufValue for Doc {
pub struct UpdateDocParams {
// message fields
pub doc_id: ::std::string::String,
pub data: ::std::vec::Vec<u8>,
pub data: ::std::string::String,
pub rev_id: i64,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
@ -508,10 +508,10 @@ impl UpdateDocParams {
::std::mem::replace(&mut self.doc_id, ::std::string::String::new())
}
// bytes data = 2;
// string data = 2;
pub fn get_data(&self) -> &[u8] {
pub fn get_data(&self) -> &str {
&self.data
}
pub fn clear_data(&mut self) {
@ -519,19 +519,19 @@ impl UpdateDocParams {
}
// Param is passed by value, moved
pub fn set_data(&mut self, v: ::std::vec::Vec<u8>) {
pub fn set_data(&mut self, v: ::std::string::String) {
self.data = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_data(&mut self) -> &mut ::std::vec::Vec<u8> {
pub fn mut_data(&mut self) -> &mut ::std::string::String {
&mut self.data
}
// Take field
pub fn take_data(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.data, ::std::vec::Vec::new())
pub fn take_data(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.data, ::std::string::String::new())
}
// int64 rev_id = 3;
@ -563,7 +563,7 @@ impl ::protobuf::Message for UpdateDocParams {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.doc_id)?;
},
2 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?;
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
},
3 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
@ -588,7 +588,7 @@ impl ::protobuf::Message for UpdateDocParams {
my_size += ::protobuf::rt::string_size(1, &self.doc_id);
}
if !self.data.is_empty() {
my_size += ::protobuf::rt::bytes_size(2, &self.data);
my_size += ::protobuf::rt::string_size(2, &self.data);
}
if self.rev_id != 0 {
my_size += ::protobuf::rt::value_size(3, self.rev_id, ::protobuf::wire_format::WireTypeVarint);
@ -603,7 +603,7 @@ impl ::protobuf::Message for UpdateDocParams {
os.write_string(1, &self.doc_id)?;
}
if !self.data.is_empty() {
os.write_bytes(2, &self.data)?;
os.write_string(2, &self.data)?;
}
if self.rev_id != 0 {
os.write_int64(3, self.rev_id)?;
@ -651,7 +651,7 @@ impl ::protobuf::Message for UpdateDocParams {
|m: &UpdateDocParams| { &m.doc_id },
|m: &mut UpdateDocParams| { &mut m.doc_id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"data",
|m: &UpdateDocParams| { &m.data },
|m: &mut UpdateDocParams| { &mut m.data },
@ -700,7 +700,7 @@ impl ::protobuf::reflect::ProtobufValue for UpdateDocParams {
pub struct DocDelta {
// message fields
pub doc_id: ::std::string::String,
pub data: ::std::vec::Vec<u8>,
pub data: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
@ -743,10 +743,10 @@ impl DocDelta {
::std::mem::replace(&mut self.doc_id, ::std::string::String::new())
}
// bytes data = 2;
// string data = 2;
pub fn get_data(&self) -> &[u8] {
pub fn get_data(&self) -> &str {
&self.data
}
pub fn clear_data(&mut self) {
@ -754,19 +754,19 @@ impl DocDelta {
}
// Param is passed by value, moved
pub fn set_data(&mut self, v: ::std::vec::Vec<u8>) {
pub fn set_data(&mut self, v: ::std::string::String) {
self.data = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_data(&mut self) -> &mut ::std::vec::Vec<u8> {
pub fn mut_data(&mut self) -> &mut ::std::string::String {
&mut self.data
}
// Take field
pub fn take_data(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.data, ::std::vec::Vec::new())
pub fn take_data(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.data, ::std::string::String::new())
}
}
@ -783,7 +783,7 @@ impl ::protobuf::Message for DocDelta {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.doc_id)?;
},
2 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?;
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@ -801,7 +801,7 @@ impl ::protobuf::Message for DocDelta {
my_size += ::protobuf::rt::string_size(1, &self.doc_id);
}
if !self.data.is_empty() {
my_size += ::protobuf::rt::bytes_size(2, &self.data);
my_size += ::protobuf::rt::string_size(2, &self.data);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
@ -813,7 +813,7 @@ impl ::protobuf::Message for DocDelta {
os.write_string(1, &self.doc_id)?;
}
if !self.data.is_empty() {
os.write_bytes(2, &self.data)?;
os.write_string(2, &self.data)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
@ -858,7 +858,7 @@ impl ::protobuf::Message for DocDelta {
|m: &DocDelta| { &m.doc_id },
|m: &mut DocDelta| { &mut m.doc_id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"data",
|m: &DocDelta| { &m.data },
|m: &mut DocDelta| { &mut m.data },
@ -1058,47 +1058,47 @@ impl ::protobuf::reflect::ProtobufValue for QueryDocParams {
static file_descriptor_proto_data: &'static [u8] = b"\
\n\tdoc.proto\"5\n\x0fCreateDocParams\x12\x0e\n\x02id\x18\x01\x20\x01(\t\
R\x02id\x12\x12\n\x04data\x18\x02\x20\x01(\x0cR\x04data\"@\n\x03Doc\x12\
R\x02id\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"@\n\x03Doc\x12\
\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04data\x18\x02\x20\x01\
(\x0cR\x04data\x12\x15\n\x06rev_id\x18\x03\x20\x01(\x03R\x05revId\"S\n\
\x0fUpdateDocParams\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\
\x12\n\x04data\x18\x02\x20\x01(\x0cR\x04data\x12\x15\n\x06rev_id\x18\x03\
\x20\x01(\x03R\x05revId\"5\n\x08DocDelta\x12\x15\n\x06doc_id\x18\x01\x20\
\x01(\tR\x05docId\x12\x12\n\x04data\x18\x02\x20\x01(\x0cR\x04data\"'\n\
\x0eQueryDocParams\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docIdJ\xe7\
\x05\n\x06\x12\x04\0\0\x16\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\
\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x17\n\
\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\x04\0\x02\0\x05\
\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\r\n\x0c\n\
\x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\n\x0b\n\x04\x04\0\x02\x01\x12\
\x03\x04\x04\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\t\n\x0c\n\
\x05\x04\0\x02\x01\x01\x12\x03\x04\n\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\
\x12\x03\x04\x11\x12\n\n\n\x02\x04\x01\x12\x04\x06\0\n\x01\n\n\n\x03\x04\
\x01\x01\x12\x03\x06\x08\x0b\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x07\x04\
\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x07\x04\n\n\x0c\n\x05\x04\x01\
\x02\0\x01\x12\x03\x07\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x07\
\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\x08\x04\x13\n\x0c\n\x05\x04\
\x01\x02\x01\x05\x12\x03\x08\x04\t\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\
\x03\x08\n\x0e\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x08\x11\x12\n\x0b\
\n\x04\x04\x01\x02\x02\x12\x03\t\x04\x15\n\x0c\n\x05\x04\x01\x02\x02\x05\
\x12\x03\t\x04\t\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\t\n\x10\n\x0c\n\
\x05\x04\x01\x02\x02\x03\x12\x03\t\x13\x14\n\n\n\x02\x04\x02\x12\x04\x0b\
\0\x0f\x01\n\n\n\x03\x04\x02\x01\x12\x03\x0b\x08\x17\n\x0b\n\x04\x04\x02\
(\tR\x04data\x12\x15\n\x06rev_id\x18\x03\x20\x01(\x03R\x05revId\"S\n\x0f\
UpdateDocParams\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x12\
\n\x04data\x18\x02\x20\x01(\tR\x04data\x12\x15\n\x06rev_id\x18\x03\x20\
\x01(\x03R\x05revId\"5\n\x08DocDelta\x12\x15\n\x06doc_id\x18\x01\x20\x01\
(\tR\x05docId\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"'\n\x0eQuer\
yDocParams\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docIdJ\xe7\x05\n\
\x06\x12\x04\0\0\x16\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\
\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x17\n\x0b\n\
\x04\x04\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\
\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\r\n\x0c\n\x05\x04\
\0\x02\0\x03\x12\x03\x03\x10\x11\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\
\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\
\0\x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\
\x04\x12\x13\n\n\n\x02\x04\x01\x12\x04\x06\0\n\x01\n\n\n\x03\x04\x01\x01\
\x12\x03\x06\x08\x0b\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x07\x04\x12\n\x0c\
\n\x05\x04\x01\x02\0\x05\x12\x03\x07\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\
\x12\x03\x07\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x07\x10\x11\n\
\x0b\n\x04\x04\x01\x02\x01\x12\x03\x08\x04\x14\n\x0c\n\x05\x04\x01\x02\
\x01\x05\x12\x03\x08\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x08\
\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x08\x12\x13\n\x0b\n\x04\
\x04\x01\x02\x02\x12\x03\t\x04\x15\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\
\x03\t\x04\t\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\t\n\x10\n\x0c\n\x05\
\x04\x01\x02\x02\x03\x12\x03\t\x13\x14\n\n\n\x02\x04\x02\x12\x04\x0b\0\
\x0f\x01\n\n\n\x03\x04\x02\x01\x12\x03\x0b\x08\x17\n\x0b\n\x04\x04\x02\
\x02\0\x12\x03\x0c\x04\x16\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0c\x04\
\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x0c\x0b\x11\n\x0c\n\x05\x04\x02\
\x02\0\x03\x12\x03\x0c\x14\x15\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\r\x04\
\x13\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\r\x04\t\n\x0c\n\x05\x04\x02\
\x02\x01\x01\x12\x03\r\n\x0e\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\r\
\x11\x12\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\x0e\x04\x15\n\x0c\n\x05\x04\
\x14\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\r\x04\n\n\x0c\n\x05\x04\x02\
\x02\x01\x01\x12\x03\r\x0b\x0f\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\r\
\x12\x13\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\x0e\x04\x15\n\x0c\n\x05\x04\
\x02\x02\x02\x05\x12\x03\x0e\x04\t\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\
\x03\x0e\n\x10\n\x0c\n\x05\x04\x02\x02\x02\x03\x12\x03\x0e\x13\x14\n\n\n\
\x02\x04\x03\x12\x04\x10\0\x13\x01\n\n\n\x03\x04\x03\x01\x12\x03\x10\x08\
\x10\n\x0b\n\x04\x04\x03\x02\0\x12\x03\x11\x04\x16\n\x0c\n\x05\x04\x03\
\x02\0\x05\x12\x03\x11\x04\n\n\x0c\n\x05\x04\x03\x02\0\x01\x12\x03\x11\
\x0b\x11\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x11\x14\x15\n\x0b\n\x04\
\x04\x03\x02\x01\x12\x03\x12\x04\x13\n\x0c\n\x05\x04\x03\x02\x01\x05\x12\
\x03\x12\x04\t\n\x0c\n\x05\x04\x03\x02\x01\x01\x12\x03\x12\n\x0e\n\x0c\n\
\x05\x04\x03\x02\x01\x03\x12\x03\x12\x11\x12\n\n\n\x02\x04\x04\x12\x04\
\x04\x03\x02\x01\x12\x03\x12\x04\x14\n\x0c\n\x05\x04\x03\x02\x01\x05\x12\
\x03\x12\x04\n\n\x0c\n\x05\x04\x03\x02\x01\x01\x12\x03\x12\x0b\x0f\n\x0c\
\n\x05\x04\x03\x02\x01\x03\x12\x03\x12\x12\x13\n\n\n\x02\x04\x04\x12\x04\
\x14\0\x16\x01\n\n\n\x03\x04\x04\x01\x12\x03\x14\x08\x16\n\x0b\n\x04\x04\
\x04\x02\0\x12\x03\x15\x04\x16\n\x0c\n\x05\x04\x04\x02\0\x05\x12\x03\x15\
\x04\n\n\x0c\n\x05\x04\x04\x02\0\x01\x12\x03\x15\x0b\x11\n\x0c\n\x05\x04\

View File

@ -31,6 +31,7 @@ pub struct Revision {
pub delta: ::std::vec::Vec<u8>,
pub md5: ::std::string::String,
pub doc_id: ::std::string::String,
pub ty: RevType,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
@ -154,6 +155,21 @@ impl Revision {
pub fn take_doc_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.doc_id, ::std::string::String::new())
}
// .RevType ty = 6;
pub fn get_ty(&self) -> RevType {
self.ty
}
pub fn clear_ty(&mut self) {
self.ty = RevType::Local;
}
// Param is passed by value, moved
pub fn set_ty(&mut self, v: RevType) {
self.ty = v;
}
}
impl ::protobuf::Message for Revision {
@ -188,6 +204,9 @@ impl ::protobuf::Message for Revision {
5 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.doc_id)?;
},
6 => {
::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.ty, 6, &mut self.unknown_fields)?
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
@ -215,6 +234,9 @@ impl ::protobuf::Message for Revision {
if !self.doc_id.is_empty() {
my_size += ::protobuf::rt::string_size(5, &self.doc_id);
}
if self.ty != RevType::Local {
my_size += ::protobuf::rt::enum_size(6, self.ty);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
@ -236,6 +258,9 @@ impl ::protobuf::Message for Revision {
if !self.doc_id.is_empty() {
os.write_string(5, &self.doc_id)?;
}
if self.ty != RevType::Local {
os.write_enum(6, ::protobuf::ProtobufEnum::value(&self.ty))?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
@ -299,6 +324,11 @@ impl ::protobuf::Message for Revision {
|m: &Revision| { &m.doc_id },
|m: &mut Revision| { &mut m.doc_id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<RevType>>(
"ty",
|m: &Revision| { &m.ty },
|m: &mut Revision| { &mut m.ty },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<Revision>(
"Revision",
fields,
@ -320,6 +350,7 @@ impl ::protobuf::Clear for Revision {
self.delta.clear();
self.md5.clear();
self.doc_id.clear();
self.ty = RevType::Local;
self.unknown_fields.clear();
}
}
@ -336,27 +367,87 @@ impl ::protobuf::reflect::ProtobufValue for Revision {
}
}
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum RevType {
Local = 0,
Remote = 1,
}
impl ::protobuf::ProtobufEnum for RevType {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<RevType> {
match value {
0 => ::std::option::Option::Some(RevType::Local),
1 => ::std::option::Option::Some(RevType::Remote),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [RevType] = &[
RevType::Local,
RevType::Remote,
];
values
}
fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
::protobuf::reflect::EnumDescriptor::new_pb_name::<RevType>("RevType", file_descriptor_proto())
})
}
}
impl ::std::marker::Copy for RevType {
}
impl ::std::default::Default for RevType {
fn default() -> Self {
RevType::Local
}
}
impl ::protobuf::reflect::ProtobufValue for RevType {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0erevision.proto\"\x80\x01\n\x08Revision\x12\x1e\n\x0bbase_rev_id\
\n\x0erevision.proto\"\x9a\x01\n\x08Revision\x12\x1e\n\x0bbase_rev_id\
\x18\x01\x20\x01(\x03R\tbaseRevId\x12\x15\n\x06rev_id\x18\x02\x20\x01(\
\x03R\x05revId\x12\x14\n\x05delta\x18\x03\x20\x01(\x0cR\x05delta\x12\x10\
\n\x03md5\x18\x04\x20\x01(\tR\x03md5\x12\x15\n\x06doc_id\x18\x05\x20\x01\
(\tR\x05docIdJ\xbd\x02\n\x06\x12\x04\0\0\x08\x01\n\x08\n\x01\x0c\x12\x03\
\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x08\x01\n\n\n\x03\x04\0\x01\x12\
\x03\x02\x08\x10\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x1a\n\x0c\n\x05\
\x04\0\x02\0\x05\x12\x03\x03\x04\t\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\
\x03\n\x15\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x18\x19\n\x0b\n\x04\
\x04\0\x02\x01\x12\x03\x04\x04\x15\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\
\x04\x04\t\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\n\x10\n\x0c\n\x05\
\x04\0\x02\x01\x03\x12\x03\x04\x13\x14\n\x0b\n\x04\x04\0\x02\x02\x12\x03\
\x05\x04\x14\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\t\n\x0c\n\x05\
\x04\0\x02\x02\x01\x12\x03\x05\n\x0f\n\x0c\n\x05\x04\0\x02\x02\x03\x12\
\x03\x05\x12\x13\n\x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x04\x13\n\x0c\n\
\x05\x04\0\x02\x03\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\0\x02\x03\x01\
\x12\x03\x06\x0b\x0e\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06\x11\x12\n\
\x0b\n\x04\x04\0\x02\x04\x12\x03\x07\x04\x16\n\x0c\n\x05\x04\0\x02\x04\
\x05\x12\x03\x07\x04\n\n\x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x07\x0b\x11\
\n\x0c\n\x05\x04\0\x02\x04\x03\x12\x03\x07\x14\x15b\x06proto3\
(\tR\x05docId\x12\x18\n\x02ty\x18\x06\x20\x01(\x0e2\x08.RevTypeR\x02ty*\
\x20\n\x07RevType\x12\t\n\x05Local\x10\0\x12\n\n\x06Remote\x10\x01J\xde\
\x03\n\x06\x12\x04\0\0\r\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\
\x04\0\x12\x04\x02\0\t\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x10\n\x0b\
\n\x04\x04\0\x02\0\x12\x03\x03\x04\x1a\n\x0c\n\x05\x04\0\x02\0\x05\x12\
\x03\x03\x04\t\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\n\x15\n\x0c\n\x05\
\x04\0\x02\0\x03\x12\x03\x03\x18\x19\n\x0b\n\x04\x04\0\x02\x01\x12\x03\
\x04\x04\x15\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\t\n\x0c\n\x05\
\x04\0\x02\x01\x01\x12\x03\x04\n\x10\n\x0c\n\x05\x04\0\x02\x01\x03\x12\
\x03\x04\x13\x14\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x14\n\x0c\n\
\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\t\n\x0c\n\x05\x04\0\x02\x02\x01\
\x12\x03\x05\n\x0f\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x12\x13\n\
\x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x04\x13\n\x0c\n\x05\x04\0\x02\x03\
\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06\x0b\x0e\
\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06\x11\x12\n\x0b\n\x04\x04\0\x02\
\x04\x12\x03\x07\x04\x16\n\x0c\n\x05\x04\0\x02\x04\x05\x12\x03\x07\x04\n\
\n\x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x07\x0b\x11\n\x0c\n\x05\x04\0\x02\
\x04\x03\x12\x03\x07\x14\x15\n\x0b\n\x04\x04\0\x02\x05\x12\x03\x08\x04\
\x13\n\x0c\n\x05\x04\0\x02\x05\x06\x12\x03\x08\x04\x0b\n\x0c\n\x05\x04\0\
\x02\x05\x01\x12\x03\x08\x0c\x0e\n\x0c\n\x05\x04\0\x02\x05\x03\x12\x03\
\x08\x11\x12\n\n\n\x02\x05\0\x12\x04\n\0\r\x01\n\n\n\x03\x05\0\x01\x12\
\x03\n\x05\x0c\n\x0b\n\x04\x05\0\x02\0\x12\x03\x0b\x04\x0e\n\x0c\n\x05\
\x05\0\x02\0\x01\x12\x03\x0b\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\
\x0b\x0c\r\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x0c\x04\x0f\n\x0c\n\x05\x05\
\0\x02\x01\x01\x12\x03\x0c\x04\n\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\
\x0c\r\x0eb\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -2,21 +2,21 @@ syntax = "proto3";
message CreateDocParams {
string id = 1;
bytes data = 2;
string data = 2;
}
message Doc {
string id = 1;
bytes data = 2;
string data = 2;
int64 rev_id = 3;
}
message UpdateDocParams {
string doc_id = 1;
bytes data = 2;
string data = 2;
int64 rev_id = 3;
}
message DocDelta {
string doc_id = 1;
bytes data = 2;
string data = 2;
}
message QueryDocParams {
string doc_id = 1;

View File

@ -6,4 +6,9 @@ message Revision {
bytes delta = 3;
string md5 = 4;
string doc_id = 5;
RevType ty = 6;
}
enum RevType {
Local = 0;
Remote = 1;
}

View File

@ -14,6 +14,13 @@ pub(crate) struct DocCache {
impl DocCache {
pub(crate) fn new() -> Self { Self { inner: DashMap::new() } }
pub(crate) fn all_docs(&self) -> Vec<Arc<EditDocContext>> {
self.inner
.iter()
.map(|kv| kv.value().clone())
.collect::<Vec<Arc<EditDocContext>>>()
}
pub(crate) fn set(&self, doc: Arc<EditDocContext>) {
let doc_id = doc.id.clone();
if self.inner.contains_key(&doc_id) {

View File

@ -2,16 +2,21 @@ use crate::{
entities::doc::{CreateDocParams, Doc, DocDelta, QueryDocParams, UpdateDocParams},
errors::{internal_error, DocError},
module::DocumentUser,
services::{cache::DocCache, doc::edit_doc_context::EditDocContext, server::Server, ws::WsDocumentManager},
services::{
cache::DocCache,
doc::{edit_doc_context::EditDocContext, rev_manager::RevisionManager},
server::Server,
ws::WsDocumentManager,
},
sql_tables::doc::{DocTable, DocTableSql, OpTableSql},
};
use bytes::Bytes;
use flowy_database::{ConnectionPool, SqliteConnection};
use crate::services::doc::rev_manager::RevisionManager;
use flowy_infra::future::{wrap_future, FnFuture};
use flowy_ot::core::Delta;
use parking_lot::RwLock;
use std::sync::Arc;
use tokio::time::{interval, Duration};
pub(crate) struct DocController {
server: Server,
@ -27,14 +32,23 @@ impl DocController {
let doc_sql = Arc::new(DocTableSql {});
let op_sql = Arc::new(OpTableSql {});
let cache = Arc::new(DocCache::new());
Self {
let controller = Self {
server,
doc_sql,
op_sql,
user,
ws,
cache,
}
cache: cache.clone(),
};
// tokio::spawn(async move {
// tokio::select! {
// _ = event_loop(cache.clone()) => {},
// }
// });
controller
}
#[tracing::instrument(skip(self, conn), err)]
@ -49,7 +63,11 @@ impl DocController {
}
#[tracing::instrument(level = "debug", skip(self, pool), err)]
pub(crate) async fn open(&self, params: QueryDocParams, pool: Arc<ConnectionPool>) -> Result<Arc<EditDocContext>, DocError> {
pub(crate) async fn open(
&self,
params: QueryDocParams,
pool: Arc<ConnectionPool>,
) -> Result<Arc<EditDocContext>, DocError> {
if self.cache.is_opened(&params.doc_id) == false {
return match self._open(params, pool).await {
Ok(doc) => Ok(doc),
@ -81,7 +99,7 @@ impl DocController {
#[tracing::instrument(level = "debug", skip(self, delta), err)]
pub(crate) fn edit_doc(&self, delta: DocDelta) -> Result<Doc, DocError> {
let edit_doc_ctx = self.cache.get(&delta.doc_id)?;
let _ = edit_doc_ctx.apply_local_delta(Bytes::from(delta.data))?;
let _ = edit_doc_ctx.compose_local_delta(Bytes::from(delta.data))?;
Ok(edit_doc_ctx.doc())
}
}
@ -104,7 +122,11 @@ impl DocController {
}
#[tracing::instrument(level = "debug", skip(self, pool), err)]
async fn read_doc_from_server(&self, params: QueryDocParams, pool: Arc<ConnectionPool>) -> Result<Arc<EditDocContext>, DocError> {
async fn read_doc_from_server(
&self,
params: QueryDocParams,
pool: Arc<ConnectionPool>,
) -> Result<Arc<EditDocContext>, DocError> {
let token = self.user.token()?;
match self.server.read_doc(&token, params).await? {
None => Err(DocError::not_found()),
@ -151,7 +173,7 @@ impl DocController {
// Opti: require upgradable_read lock and then upgrade to write lock using
// RwLockUpgradableReadGuard::upgrade(xx) of ws
let doc_id = doc.id.clone();
let delta = Delta::from_bytes(doc.data)?;
let delta = Delta::from_bytes(&doc.data)?;
let ws_sender = self.ws.read().sender();
let rev_manager = RevisionManager::new(&doc_id, doc.rev_id, self.op_sql.clone(), pool, ws_sender);
let edit_ctx = Arc::new(EditDocContext::new(&doc_id, delta, rev_manager)?);
@ -160,3 +182,14 @@ impl DocController {
Ok(edit_ctx)
}
}
#[allow(dead_code)]
fn event_loop(_cache: Arc<DocCache>) -> FnFuture<()> {
let mut i = interval(Duration::from_secs(3));
wrap_future(async move {
loop {
// cache.all_docs().iter().for_each(|doc| doc.tick());
i.tick().await;
}
})
}

View File

@ -2,7 +2,7 @@ use crate::{
errors::DocError,
services::doc::{view::View, History, UndoResult, RECORD_THRESHOLD},
};
use bytes::Bytes;
use flowy_ot::core::*;
pub trait DocumentData {
@ -57,10 +57,29 @@ impl Document {
pub fn set_delta(&mut self, data: Delta) { self.delta = data; }
pub fn apply_delta(&mut self, delta: Delta) -> Result<(), DocError> {
log::trace!("Apply delta: {}", delta);
let _ = self.add_delta(&delta)?;
log::debug!("Document: {}", self.to_json());
pub fn compose_delta(&mut self, delta: &Delta) -> Result<(), DocError> {
let composed_delta = self.delta.compose(delta)?;
let mut undo_delta = delta.invert(&self.delta);
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::trace!("compose previous change");
log::trace!("current = {}", undo_delta);
log::trace!("previous = {}", last_delta);
undo_delta = undo_delta.compose(&last_delta)?;
}
} else {
self.last_edit_time = now;
}
log::trace!("👉 receive change undo: {}", undo_delta);
if !undo_delta.is_empty() {
self.history.record(undo_delta);
}
log::trace!("document delta: {}", &composed_delta);
self.delta = composed_delta;
Ok(())
}
@ -71,7 +90,7 @@ impl Document {
let text = data.into_string()?;
let delta = self.view.insert(&self.delta, &text, interval)?;
log::trace!("👉 receive change: {}", delta);
self.add_delta(&delta)?;
self.compose_delta(&delta)?;
Ok(delta)
}
@ -81,19 +100,19 @@ impl Document {
let delete = self.view.delete(&self.delta, interval)?;
if !delete.is_empty() {
log::trace!("👉 receive change: {}", delete);
let _ = self.add_delta(&delete)?;
let _ = self.compose_delta(&delete)?;
}
Ok(delete)
}
pub fn format(&mut self, interval: Interval, attribute: Attribute) -> Result<(), DocError> {
pub fn format(&mut self, interval: Interval, attribute: Attribute) -> Result<Delta, DocError> {
let _ = validate_interval(&self.delta, &interval)?;
log::trace!("format with {} at {}", attribute, interval);
let format_delta = self.view.format(&self.delta, attribute.clone(), interval).unwrap();
log::trace!("👉 receive change: {}", format_delta);
self.add_delta(&format_delta)?;
Ok(())
self.compose_delta(&format_delta)?;
Ok(format_delta)
}
pub fn replace<T: DocumentData>(&mut self, interval: Interval, data: T) -> Result<Delta, DocError> {
@ -103,7 +122,7 @@ impl Document {
if !text.is_empty() {
delta = self.view.insert(&self.delta, &text, interval)?;
log::trace!("👉 receive change: {}", delta);
self.add_delta(&delta)?;
self.compose_delta(&delta)?;
}
if !interval.is_empty() {
@ -148,32 +167,6 @@ impl Document {
}
impl Document {
fn add_delta(&mut self, delta: &Delta) -> Result<(), DocError> {
let composed_delta = self.delta.compose(delta)?;
let mut undo_delta = delta.invert(&self.delta);
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::trace!("compose previous change");
log::trace!("current = {}", undo_delta);
log::trace!("previous = {}", last_delta);
undo_delta = undo_delta.compose(&last_delta)?;
}
} else {
self.last_edit_time = now;
}
log::trace!("👉 receive change undo: {}", undo_delta);
if !undo_delta.is_empty() {
self.history.record(undo_delta);
}
log::trace!("document delta: {}", &composed_delta);
self.delta = composed_delta;
Ok(())
}
fn invert_change(&self, change: &Delta) -> Result<(Delta, Delta), DocError> {
// c = a.compose(b)
// d = b.invert(a)

View File

@ -6,16 +6,16 @@ use crate::{
errors::*,
services::{
doc::{rev_manager::RevisionManager, Document},
util::{bytes_to_rev_id, md5},
ws::{WsDocumentHandler, WsDocumentSender},
util::bytes_to_rev_id,
ws::WsDocumentHandler,
},
sql_tables::{OpTable, OpTableSql},
sql_tables::{OpTableSql, RevTable},
};
use bytes::Bytes;
use flowy_ot::core::Delta;
use parking_lot::RwLock;
use std::{convert::TryFrom, sync::Arc};
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
pub type DocId = String;
@ -30,49 +30,30 @@ impl EditDocContext {
let id = doc_id.to_owned();
let rev_manager = Arc::new(rev_manager);
let document = Arc::new(RwLock::new(Document::from_delta(delta)));
let edit_context = Self { id, document, rev_manager };
edit_context.composing_delta();
let edit_context = Self {
id,
document,
rev_manager,
};
Ok(edit_context)
}
pub(crate) fn doc(&self) -> Doc {
Doc {
id: self.id.clone(),
data: self.document.read().to_bytes(),
rev_id: self.rev_manager.rev(),
data: self.document.read().to_json(),
rev_id: self.rev_manager.rev_id(),
}
}
#[tracing::instrument(level = "debug", skip(self, data), err)]
pub(crate) fn apply_local_delta(&self, data: Bytes) -> Result<(), DocError> {
let doc_id = self.id.clone();
let (base_rev_id, rev_id) = self.rev_manager.next_rev();
let revision = Revision::new(base_rev_id, rev_id, data.to_vec(), md5(&data), doc_id);
pub(crate) fn compose_local_delta(&self, data: Bytes) -> Result<(), DocError> {
let delta = Delta::from_bytes(&data)?;
self.document.write().compose_delta(&delta)?;
self.rev_manager.add_delta(data);
let delta = Delta::from_bytes(data.to_vec())?;
self.document.write().apply_delta(delta)?;
self.rev_manager.add_local(revision);
Ok(())
}
fn composing_delta(&self) {
let rev_manager = self.rev_manager.clone();
let document = self.document.clone();
tokio::spawn(async move {
let notified = rev_manager.notified();
tokio::select! {
_ = notified => {
if let Some(delta) = rev_manager.next_compose_delta() {
log::info!("😁receive delta: {:?}", delta);
document.write().apply_delta(delta).unwrap();
log::info!("😁Document: {:?}", document.read().to_plain_string());
}
}
}
});
}
}
impl WsDocumentHandler for EditDocContext {
@ -82,14 +63,18 @@ impl WsDocumentHandler for EditDocContext {
WsDataType::Rev => {
let bytes = Bytes::from(doc_data.data);
let revision = Revision::try_from(bytes)?;
self.rev_manager.add_remote(revision);
self.rev_manager.add_revision(revision);
self.rev_manager.next_compose_delta(|delta| {
let _ = self.document.write().compose_delta(delta)?;
log::debug!("😁Document: {:?}", self.document.read().to_plain_string());
Ok(())
});
},
WsDataType::Acked => {
let rev_id = bytes_to_rev_id(doc_data.data)?;
self.rev_manager.remove(rev_id);
},
}
Result::<(), DocError>::Ok(())
};

View File

@ -1,21 +1,20 @@
use crate::{
entities::{
doc::Revision,
ws::{WsDataType, WsDocumentData},
},
entities::doc::{RevType, Revision},
errors::{internal_error, DocError},
services::{
util::{bytes_to_rev_id, RevIdCounter},
util::{md5, RevIdCounter},
ws::{WsDocumentHandler, WsDocumentSender},
},
sql_tables::{OpTable, OpTableSql},
sql_tables::{OpTableSql, RevTable},
};
use bytes::Bytes;
use flowy_database::ConnectionPool;
use flowy_infra::future::wrap_future;
use flowy_ot::core::Delta;
use parking_lot::RwLock;
use std::{collections::BTreeMap, sync::Arc};
use std::{
collections::{BTreeMap, VecDeque},
sync::Arc,
};
use tokio::sync::{futures::Notified, Notify};
pub struct RevisionManager {
@ -24,7 +23,8 @@ pub struct RevisionManager {
pool: Arc<ConnectionPool>,
rev_id_counter: RevIdCounter,
ws_sender: Arc<dyn WsDocumentSender>,
rev_cache: RwLock<BTreeMap<i64, Revision>>,
local_rev_cache: Arc<RwLock<BTreeMap<i64, Revision>>>,
remote_rev_cache: RwLock<VecDeque<Revision>>,
notify: Notify,
}
@ -37,59 +37,90 @@ impl RevisionManager {
ws_sender: Arc<dyn WsDocumentSender>,
) -> Self {
let rev_id_counter = RevIdCounter::new(rev_id);
let rev_cache = RwLock::new(BTreeMap::new());
let local_rev_cache = Arc::new(RwLock::new(BTreeMap::new()));
let remote_rev_cache = RwLock::new(VecDeque::new());
Self {
doc_id: doc_id.to_owned(),
op_sql,
pool,
rev_id_counter,
ws_sender,
rev_cache,
local_rev_cache,
remote_rev_cache,
notify: Notify::new(),
}
}
pub fn next_compose_delta(&self) -> Option<Delta> {
// let delta = Delta::from_bytes(revision.delta)?;
//
// log::debug!("Remote delta: {:?}", delta);
pub fn next_compose_delta<F>(&self, mut f: F)
where
F: FnMut(&Delta) -> Result<(), DocError>,
{
if let Some(rev) = self.remote_rev_cache.write().pop_front() {
match Delta::from_bytes(&rev.delta) {
Ok(delta) => match f(&delta) {
Ok(_) => {},
Err(e) => {
log::error!("{}", e);
self.remote_rev_cache.write().push_front(rev);
},
},
Err(_) => {},
}
}
}
pub fn notified(&self) -> Notified { self.notify.notified() }
#[tracing::instrument(level = "debug", skip(self, delta_data))]
pub fn add_delta(&self, delta_data: Bytes) -> Result<(), DocError> {
let (base_rev_id, rev_id) = self.next_rev_id();
let revision = Revision::new(
base_rev_id,
rev_id,
delta_data.to_vec(),
md5(&delta_data),
self.doc_id.clone(),
RevType::Local,
);
let _ = self.add_revision(revision)?;
Ok(())
}
pub fn next_rev(&self) -> (i64, i64) {
#[tracing::instrument(level = "debug", skip(self, revision))]
pub fn add_revision(&self, revision: Revision) -> Result<(), DocError> {
match revision.ty {
RevType::Local => {
self.local_rev_cache.write().insert(revision.rev_id, revision.clone());
// self.save_revision(revision.clone());
match self.ws_sender.send(revision.into()) {
Ok(_) => {},
Err(e) => {
log::error!("Send delta failed: {:?}", e);
},
}
},
RevType::Remote => {
self.remote_rev_cache.write().push_back(revision);
self.notify.notify_waiters();
},
}
Ok(())
}
pub fn remove(&self, rev_id: i64) -> Result<(), DocError> {
self.local_rev_cache.write().remove(&rev_id);
// self.delete_revision(rev_id);
Ok(())
}
pub fn rev_notified(&self) -> Notified { self.notify.notified() }
pub fn next_rev_id(&self) -> (i64, i64) {
let cur = self.rev_id_counter.value();
let next = self.rev_id_counter.next();
(cur, next)
}
pub fn rev(&self) -> i64 { self.rev_id_counter.value() }
pub fn add_local(&self, revision: Revision) -> Result<(), DocError> {
self.rev_cache.write().insert(revision.rev_id, revision.clone());
match self.ws_sender.send(revision.into()) {
Ok(_) => {},
Err(e) => {
log::error!("Send delta failed: {:?}", e);
},
}
// self.save_revision(revision.clone());
Ok(())
}
#[tracing::instrument(level = "debug", skip(self, revision))]
pub fn add_remote(&self, revision: Revision) -> Result<(), DocError> {
self.rev_cache.write().insert(revision.rev_id, revision);
// self.save_revision(revision.clone());
self.notify.notify_waiters();
Ok(())
}
pub fn remove(&self, rev_id: i64) -> Result<(), DocError> {
self.rev_cache.write().remove(&rev_id);
// self.delete_revision(rev_id);
Ok(())
}
pub fn rev_id(&self) -> i64 { self.rev_id_counter.value() }
fn save_revision(&self, revision: Revision) {
let op_sql = self.op_sql.clone();
@ -97,7 +128,7 @@ impl RevisionManager {
tokio::spawn(async move {
let conn = &*pool.get().map_err(internal_error).unwrap();
let result = conn.immediate_transaction::<_, DocError, _>(|| {
let op_table: OpTable = revision.into();
let op_table: RevTable = revision.into();
let _ = op_sql.create_op_table(op_table, conn).unwrap();
Ok(())
});

View File

@ -1,35 +1,35 @@
use crate::{
errors::DocError,
sql_tables::doc::{OpChangeset, OpTable},
sql_tables::doc::{RevChangeset, RevTable},
};
use flowy_database::{
prelude::*,
schema::{op_table, op_table::dsl},
schema::{rev_table, rev_table::dsl},
SqliteConnection,
};
pub struct OpTableSql {}
impl OpTableSql {
pub(crate) fn create_op_table(&self, op_table: OpTable, conn: &SqliteConnection) -> Result<(), DocError> {
let _ = diesel::insert_into(op_table::table).values(op_table).execute(conn)?;
pub(crate) fn create_op_table(&self, op_table: RevTable, conn: &SqliteConnection) -> Result<(), DocError> {
let _ = diesel::insert_into(rev_table::table).values(op_table).execute(conn)?;
Ok(())
}
pub(crate) fn update_op_table(&self, changeset: OpChangeset, conn: &SqliteConnection) -> Result<(), DocError> {
let filter = dsl::op_table.filter(op_table::dsl::rev_id.eq(changeset.rev_id));
pub(crate) fn update_op_table(&self, changeset: RevChangeset, conn: &SqliteConnection) -> Result<(), DocError> {
let filter = dsl::rev_table.filter(rev_table::dsl::rev_id.eq(changeset.rev_id));
let affected_row = diesel::update(filter).set(changeset).execute(conn)?;
debug_assert_eq!(affected_row, 1);
Ok(())
}
pub(crate) fn read_op_table(&self, conn: &SqliteConnection) -> Result<Vec<OpTable>, DocError> {
let ops = dsl::op_table.load::<OpTable>(conn)?;
pub(crate) fn read_op_table(&self, conn: &SqliteConnection) -> Result<Vec<RevTable>, DocError> {
let ops = dsl::rev_table.load::<RevTable>(conn)?;
Ok(ops)
}
pub(crate) fn delete_op_table(&self, rev_id: i64, conn: &SqliteConnection) -> Result<(), DocError> {
let filter = dsl::op_table.filter(op_table::dsl::rev_id.eq(rev_id));
let filter = dsl::rev_table.filter(rev_table::dsl::rev_id.eq(rev_id));
let affected_row = diesel::delete(filter).execute(conn)?;
debug_assert_eq!(affected_row, 1);
Ok(())

View File

@ -1,68 +1,104 @@
use crate::entities::doc::Revision;
use crate::entities::doc::{RevType, Revision};
use diesel::sql_types::Integer;
use flowy_database::schema::op_table;
use flowy_database::schema::rev_table;
#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
#[table_name = "op_table"]
#[table_name = "rev_table"]
#[primary_key(doc_id)]
pub(crate) struct OpTable {
pub(crate) struct RevTable {
pub(crate) doc_id: String,
pub(crate) base_rev_id: i64,
pub(crate) rev_id: i64,
pub(crate) data: Vec<u8>,
pub(crate) md5: String,
pub(crate) state: OpState,
pub(crate) state: RevState,
pub(crate) ty: RevTableType,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, FromSqlRow, AsExpression)]
#[repr(i32)]
#[sql_type = "Integer"]
pub enum OpState {
pub enum RevState {
Local = 0,
Acked = 1,
}
impl std::default::Default for OpState {
fn default() -> Self { OpState::Local }
impl std::default::Default for RevState {
fn default() -> Self { RevState::Local }
}
impl std::convert::From<i32> for OpState {
impl std::convert::From<i32> for RevState {
fn from(value: i32) -> Self {
match value {
0 => OpState::Local,
1 => OpState::Acked,
0 => RevState::Local,
1 => RevState::Acked,
o => {
log::error!("Unsupported view type {}, fallback to ViewType::Docs", o);
OpState::Local
log::error!("Unsupported rev state {}, fallback to RevState::Local", o);
RevState::Local
},
}
}
}
impl OpState {
impl RevState {
pub fn value(&self) -> i32 { *self as i32 }
}
impl_sql_integer_expression!(RevState);
impl_sql_integer_expression!(OpState);
#[derive(AsChangeset, Identifiable, Default, Debug)]
#[table_name = "op_table"]
#[primary_key(doc_id)]
pub(crate) struct OpChangeset {
pub(crate) doc_id: String,
pub(crate) rev_id: i64,
pub(crate) state: Option<OpState>,
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, FromSqlRow, AsExpression)]
#[repr(i32)]
#[sql_type = "Integer"]
pub enum RevTableType {
Local = 0,
Remote = 1,
}
impl std::convert::Into<OpTable> for Revision {
fn into(self) -> OpTable {
OpTable {
impl std::default::Default for RevTableType {
fn default() -> Self { RevTableType::Local }
}
impl std::convert::From<i32> for RevTableType {
fn from(value: i32) -> Self {
match value {
0 => RevTableType::Local,
1 => RevTableType::Remote,
o => {
log::error!("Unsupported rev type {}, fallback to RevTableType::Local", o);
RevTableType::Local
},
}
}
}
impl RevTableType {
pub fn value(&self) -> i32 { *self as i32 }
}
impl_sql_integer_expression!(RevTableType);
#[derive(AsChangeset, Identifiable, Default, Debug)]
#[table_name = "rev_table"]
#[primary_key(doc_id)]
pub(crate) struct RevChangeset {
pub(crate) doc_id: String,
pub(crate) rev_id: i64,
pub(crate) state: Option<RevState>,
}
impl std::convert::Into<RevTable> for Revision {
fn into(self) -> RevTable {
RevTable {
doc_id: self.doc_id,
base_rev_id: self.base_rev_id,
rev_id: self.rev_id,
data: self.delta,
md5: self.md5,
state: OpState::Local,
state: RevState::Local,
ty: rev_ty_to_rev_state(self.ty),
}
}
}
fn rev_ty_to_rev_state(ty: RevType) -> RevTableType {
match ty {
RevType::Local => RevTableType::Local,
RevType::Remote => RevTableType::Remote,
}
}

View File

@ -5,7 +5,7 @@ use flowy_database::schema::doc_table;
#[table_name = "doc_table"]
pub(crate) struct DocTable {
pub(crate) id: String,
pub(crate) data: Vec<u8>,
pub(crate) data: String,
pub(crate) revision: i64,
}
@ -23,7 +23,7 @@ impl DocTable {
#[table_name = "doc_table"]
pub(crate) struct DocTableChangeset {
pub id: String,
pub data: Vec<u8>,
pub data: String,
}
impl DocTableChangeset {

View File

@ -7,7 +7,7 @@ fn attributes_bold_added() {
let ops = vec![
Insert(0, "123456", 0),
Bold(0, Interval::new(3, 5), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"123"},
@ -24,9 +24,9 @@ fn attributes_bold_added_and_invert_all() {
let ops = vec![
Insert(0, "123", 0),
Bold(0, Interval::new(0, 3), true),
AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
Bold(0, Interval::new(0, 3), false),
AssertOpsJson(0, r#"[{"insert":"123"}]"#),
AssertDocJson(0, r#"[{"insert":"123"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -36,9 +36,9 @@ fn attributes_bold_added_and_invert_partial_suffix() {
let ops = vec![
Insert(0, "1234", 0),
Bold(0, Interval::new(0, 4), true),
AssertOpsJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
Bold(0, Interval::new(2, 4), false),
AssertOpsJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
AssertDocJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -48,11 +48,11 @@ fn attributes_bold_added_and_invert_partial_suffix2() {
let ops = vec![
Insert(0, "1234", 0),
Bold(0, Interval::new(0, 4), true),
AssertOpsJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
Bold(0, Interval::new(2, 4), false),
AssertOpsJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
AssertDocJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
Bold(0, Interval::new(2, 4), true),
AssertOpsJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -62,19 +62,22 @@ fn attributes_bold_added_with_new_line() {
let ops = vec![
Insert(0, "123456", 0),
Bold(0, Interval::new(0, 6), true),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
AssertDocJson(
0,
r#"[{"insert":"123456","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
),
Insert(0, "\n", 3),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"},{"insert":"456","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
),
Insert(0, "\n", 4),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n\n"},{"insert":"456","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
),
Insert(0, "a", 4),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\na\n"},{"insert":"456","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
),
@ -87,9 +90,9 @@ fn attributes_bold_added_and_invert_partial_prefix() {
let ops = vec![
Insert(0, "1234", 0),
Bold(0, Interval::new(0, 4), true),
AssertOpsJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
Bold(0, Interval::new(0, 2), false),
AssertOpsJson(0, r#"[{"insert":"12"},{"insert":"34","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"12"},{"insert":"34","attributes":{"bold":"true"}}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -99,9 +102,9 @@ fn attributes_bold_added_consecutive() {
let ops = vec![
Insert(0, "1234", 0),
Bold(0, Interval::new(0, 1), true),
AssertOpsJson(0, r#"[{"insert":"1","attributes":{"bold":"true"}},{"insert":"234"}]"#),
AssertDocJson(0, r#"[{"insert":"1","attributes":{"bold":"true"}},{"insert":"234"}]"#),
Bold(0, Interval::new(1, 2), true),
AssertOpsJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
AssertDocJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -112,12 +115,12 @@ fn attributes_bold_added_italic() {
Insert(0, "1234", 0),
Bold(0, Interval::new(0, 4), true),
Italic(0, Interval::new(0, 4), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"1234","attributes":{"italic":"true","bold":"true"}},{"insert":"\n"}]"#,
),
Insert(0, "5678", 4),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"12345678","attributes":{"bold":"true","italic":"true"}},{"insert":"\n"}]"#,
),
@ -130,9 +133,9 @@ fn attributes_bold_added_italic2() {
let ops = vec![
Insert(0, "123456", 0),
Bold(0, Interval::new(0, 6), true),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
Italic(0, Interval::new(0, 2), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12","attributes":{"italic":"true","bold":"true"}},
@ -140,7 +143,7 @@ fn attributes_bold_added_italic2() {
"#,
),
Italic(0, Interval::new(4, 6), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12","attributes":{"italic":"true","bold":"true"}},
@ -159,7 +162,7 @@ fn attributes_bold_added_italic3() {
Insert(0, "123456789", 0),
Bold(0, Interval::new(0, 5), true),
Italic(0, Interval::new(0, 2), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12","attributes":{"bold":"true","italic":"true"}},
@ -167,7 +170,7 @@ fn attributes_bold_added_italic3() {
"#,
),
Italic(0, Interval::new(2, 4), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"1234","attributes":{"bold":"true","italic":"true"}},
@ -176,7 +179,7 @@ fn attributes_bold_added_italic3() {
"#,
),
Bold(0, Interval::new(7, 9), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"1234","attributes":{"bold":"true","italic":"true"}},
@ -196,7 +199,7 @@ fn attributes_bold_added_italic_delete() {
Insert(0, "123456789", 0),
Bold(0, Interval::new(0, 5), true),
Italic(0, Interval::new(0, 2), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12","attributes":{"italic":"true","bold":"true"}},
@ -204,14 +207,14 @@ fn attributes_bold_added_italic_delete() {
"#,
),
Italic(0, Interval::new(2, 4), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"1234","attributes":{"bold":"true","italic":"true"}}
,{"insert":"5","attributes":{"bold":"true"}},{"insert":"6789"}]"#,
),
Bold(0, Interval::new(7, 9), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"1234","attributes":{"bold":"true","italic":"true"}},
@ -220,7 +223,7 @@ fn attributes_bold_added_italic_delete() {
"#,
),
Delete(0, Interval::new(0, 5)),
AssertOpsJson(0, r#"[{"insert":"67"},{"insert":"89","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"67"},{"insert":"89","attributes":{"bold":"true"}}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
@ -230,9 +233,9 @@ fn attributes_bold_added_italic_delete() {
fn attributes_merge_inserted_text_with_same_attribute() {
let ops = vec![
InsertBold(0, "123", Interval::new(0, 3)),
AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
InsertBold(0, "456", Interval::new(3, 6)),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -241,12 +244,12 @@ fn attributes_merge_inserted_text_with_same_attribute() {
fn attributes_compose_attr_attributes_with_attr_attributes_test() {
let ops = vec![
InsertBold(0, "123456", Interval::new(0, 6)),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
InsertBold(1, "7", Interval::new(0, 1)),
AssertOpsJson(1, r#"[{"insert":"7","attributes":{"bold":"true"}}]"#),
AssertDocJson(1, r#"[{"insert":"7","attributes":{"bold":"true"}}]"#),
Transform(0, 1),
AssertOpsJson(0, r#"[{"insert":"1234567","attributes":{"bold":"true"}}]"#),
AssertOpsJson(1, r#"[{"insert":"1234567","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"1234567","attributes":{"bold":"true"}}]"#),
AssertDocJson(1, r#"[{"insert":"1234567","attributes":{"bold":"true"}}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
@ -259,7 +262,7 @@ fn attributes_compose_attr_attributes_with_attr_attributes_test2() {
Bold(0, Interval::new(0, 6), true),
Italic(0, Interval::new(0, 2), true),
Italic(0, Interval::new(4, 6), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12","attributes":{"bold":"true","italic":"true"}},
@ -268,9 +271,9 @@ fn attributes_compose_attr_attributes_with_attr_attributes_test2() {
"#,
),
InsertBold(1, "7", Interval::new(0, 1)),
AssertOpsJson(1, r#"[{"insert":"7","attributes":{"bold":"true"}}]"#),
AssertDocJson(1, r#"[{"insert":"7","attributes":{"bold":"true"}}]"#),
Transform(0, 1),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12","attributes":{"italic":"true","bold":"true"}},
@ -279,7 +282,7 @@ fn attributes_compose_attr_attributes_with_attr_attributes_test2() {
{"insert":"7","attributes":{"bold":"true"}}]
"#,
),
AssertOpsJson(
AssertDocJson(
1,
r#"[
{"insert":"12","attributes":{"italic":"true","bold":"true"}},
@ -299,12 +302,12 @@ fn attributes_compose_attr_attributes_with_no_attr_attributes_test() {
let ops = vec![
InsertBold(0, "123456", Interval::new(0, 6)),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
Insert(1, "7", 0),
AssertOpsJson(1, r#"[{"insert":"7"}]"#),
AssertDocJson(1, r#"[{"insert":"7"}]"#),
Transform(0, 1),
AssertOpsJson(0, expected),
AssertOpsJson(1, expected),
AssertDocJson(0, expected),
AssertDocJson(1, expected),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -313,9 +316,9 @@ fn attributes_compose_attr_attributes_with_no_attr_attributes_test() {
fn attributes_replace_heading() {
let ops = vec![
InsertBold(0, "123456", Interval::new(0, 6)),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
Delete(0, Interval::new(0, 2)),
AssertOpsJson(0, r#"[{"insert":"3456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"3456","attributes":{"bold":"true"}}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
@ -325,9 +328,9 @@ fn attributes_replace_heading() {
fn attributes_replace_trailing() {
let ops = vec![
InsertBold(0, "123456", Interval::new(0, 6)),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
Delete(0, Interval::new(5, 6)),
AssertOpsJson(0, r#"[{"insert":"12345","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"12345","attributes":{"bold":"true"}}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
@ -337,11 +340,11 @@ fn attributes_replace_trailing() {
fn attributes_replace_middle() {
let ops = vec![
InsertBold(0, "123456", Interval::new(0, 6)),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
Delete(0, Interval::new(0, 2)),
AssertOpsJson(0, r#"[{"insert":"3456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"3456","attributes":{"bold":"true"}}]"#),
Delete(0, Interval::new(2, 4)),
AssertOpsJson(0, r#"[{"insert":"34","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"34","attributes":{"bold":"true"}}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
@ -351,9 +354,9 @@ fn attributes_replace_middle() {
fn attributes_replace_all() {
let ops = vec![
InsertBold(0, "123456", Interval::new(0, 6)),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
Delete(0, Interval::new(0, 6)),
AssertOpsJson(0, r#"[]"#),
AssertDocJson(0, r#"[]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
@ -363,9 +366,9 @@ fn attributes_replace_all() {
fn attributes_replace_with_text() {
let ops = vec![
InsertBold(0, "123456", Interval::new(0, 6)),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
Replace(0, Interval::new(0, 3), "ab"),
AssertOpsJson(0, r#"[{"insert":"ab"},{"insert":"456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"ab"},{"insert":"456","attributes":{"bold":"true"}}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
@ -376,9 +379,9 @@ fn attributes_header_insert_newline_at_middle() {
let ops = vec![
Insert(0, "123456", 0),
Header(0, Interval::new(0, 6), 1),
AssertOpsJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}}]"#),
AssertDocJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}}]"#),
Insert(0, "\n", 3),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123"},{"insert":"\n","attributes":{"header":1}},{"insert":"456"},{"insert":"\n","attributes":{"header":1}}]"#,
),
@ -393,17 +396,17 @@ fn attributes_header_insert_double_newline_at_middle() {
Insert(0, "123456", 0),
Header(0, Interval::new(0, 6), 1),
Insert(0, "\n", 3),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123"},{"insert":"\n","attributes":{"header":1}},{"insert":"456"},{"insert":"\n","attributes":{"header":1}}]"#,
),
Insert(0, "\n", 4),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123"},{"insert":"\n\n","attributes":{"header":1}},{"insert":"456"},{"insert":"\n","attributes":{"header":1}}]"#,
),
Insert(0, "\n", 4),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123"},{"insert":"\n\n","attributes":{"header":1}},{"insert":"\n456"},{"insert":"\n","attributes":{"header":1}}]"#,
),
@ -418,7 +421,7 @@ fn attributes_header_insert_newline_at_trailing() {
Insert(0, "123456", 0),
Header(0, Interval::new(0, 6), 1),
Insert(0, "\n", 6),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}},{"insert":"\n"}]"#,
),
@ -434,7 +437,7 @@ fn attributes_header_insert_double_newline_at_trailing() {
Header(0, Interval::new(0, 6), 1),
Insert(0, "\n", 6),
Insert(0, "\n", 7),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}},{"insert":"\n\n"}]"#,
),
@ -448,7 +451,7 @@ fn attributes_link_added() {
let ops = vec![
Insert(0, "123456", 0),
Link(0, Interval::new(0, 6), "https://appflowy.io"),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
),
@ -463,7 +466,7 @@ fn attributes_link_format_with_bold() {
Insert(0, "123456", 0),
Link(0, Interval::new(0, 6), "https://appflowy.io"),
Bold(0, Interval::new(0, 3), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"123","attributes":{"bold":"true","link":"https://appflowy.io"}},
@ -481,12 +484,12 @@ fn attributes_link_insert_char_at_head() {
let ops = vec![
Insert(0, "123456", 0),
Link(0, Interval::new(0, 6), "https://appflowy.io"),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
),
Insert(0, "a", 0),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"a"},{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
),
@ -501,7 +504,7 @@ fn attributes_link_insert_char_at_middle() {
Insert(0, "1256", 0),
Link(0, Interval::new(0, 4), "https://appflowy.io"),
Insert(0, "34", 2),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
),
@ -515,12 +518,12 @@ fn attributes_link_insert_char_at_trailing() {
let ops = vec![
Insert(0, "123456", 0),
Link(0, Interval::new(0, 6), "https://appflowy.io"),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
),
Insert(0, "a", 6),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"a\n"}]"#,
),
@ -535,7 +538,7 @@ fn attributes_link_insert_newline_at_middle() {
Insert(0, "123456", 0),
Link(0, Interval::new(0, 6), "https://appflowy.io"),
Insert(0, NEW_LINE, 3),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"},{"insert":"456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
),
@ -549,9 +552,9 @@ fn attributes_link_auto_format() {
let site = "https://appflowy.io";
let ops = vec![
Insert(0, site, 0),
AssertOpsJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
AssertDocJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
Insert(0, WHITESPACE, site.len()),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"https://appflowy.io","attributes":{"link":"https://appflowy.io/"}},{"insert":" \n"}]"#,
),
@ -567,7 +570,7 @@ fn attributes_link_auto_format_exist() {
Insert(0, site, 0),
Link(0, Interval::new(0, site.len()), site),
Insert(0, WHITESPACE, site.len()),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"https://appflowy.io","attributes":{"link":"https://appflowy.io/"}},{"insert":" \n"}]"#,
),
@ -583,7 +586,7 @@ fn attributes_link_auto_format_exist2() {
Insert(0, site, 0),
Link(0, Interval::new(0, site.len() / 2), site),
Insert(0, WHITESPACE, site.len()),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"https://a","attributes":{"link":"https://appflowy.io"}},{"insert":"ppflowy.io \n"}]"#,
),
@ -597,7 +600,7 @@ fn attributes_bullet_added() {
let ops = vec![
Insert(0, "12", 0),
Bullet(0, Interval::new(0, 1), true),
AssertOpsJson(0, r#"[{"insert":"12"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
AssertDocJson(0, r#"[{"insert":"12"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
@ -608,11 +611,14 @@ fn attributes_bullet_added_2() {
let ops = vec![
Insert(0, "1", 0),
Bullet(0, Interval::new(0, 1), true),
AssertOpsJson(0, r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
AssertDocJson(0, r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
Insert(0, NEW_LINE, 1),
AssertOpsJson(0, r#"[{"insert":"1"},{"insert":"\n\n","attributes":{"list":"bullet"}}]"#),
AssertDocJson(
0,
r#"[{"insert":"1"},{"insert":"\n\n","attributes":{"list":"bullet"}}]"#,
),
Insert(0, "2", 2),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
),
@ -629,7 +635,7 @@ fn attributes_bullet_remove_partial() {
Insert(0, NEW_LINE, 1),
Insert(0, "2", 2),
Bullet(0, Interval::new(2, 3), false),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2\n"}]"#,
),
@ -645,7 +651,7 @@ fn attributes_bullet_auto_exit() {
Bullet(0, Interval::new(0, 1), true),
Insert(0, NEW_LINE, 1),
Insert(0, NEW_LINE, 2),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"\n"}]"#,
),
@ -660,9 +666,12 @@ fn attributes_preserve_block_when_insert_newline_inside() {
Insert(0, "12", 0),
Bullet(0, Interval::new(0, 2), true),
Insert(0, NEW_LINE, 2),
AssertOpsJson(0, r#"[{"insert":"12"},{"insert":"\n\n","attributes":{"list":"bullet"}}]"#),
AssertDocJson(
0,
r#"[{"insert":"12"},{"insert":"\n\n","attributes":{"list":"bullet"}}]"#,
),
Insert(0, "34", 3),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12"},{"insert":"\n","attributes":{"list":"bullet"}},
@ -670,7 +679,7 @@ fn attributes_preserve_block_when_insert_newline_inside() {
]"#,
),
Insert(0, NEW_LINE, 3),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12"},{"insert":"\n\n","attributes":{"list":"bullet"}},
@ -678,7 +687,7 @@ fn attributes_preserve_block_when_insert_newline_inside() {
]"#,
),
Insert(0, "ab", 3),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12"},{"insert":"\n","attributes":{"list":"bullet"}},
@ -697,12 +706,12 @@ fn attributes_preserve_header_format_on_merge() {
Insert(0, "123456", 0),
Header(0, Interval::new(0, 6), 1),
Insert(0, NEW_LINE, 3),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123"},{"insert":"\n","attributes":{"header":1}},{"insert":"456"},{"insert":"\n","attributes":{"header":1}}]"#,
),
Delete(0, Interval::new(3, 4)),
AssertOpsJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}}]"#),
AssertDocJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
@ -714,12 +723,15 @@ fn attributes_preserve_list_format_on_merge() {
Insert(0, "123456", 0),
Bullet(0, Interval::new(0, 6), true),
Insert(0, NEW_LINE, 3),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
),
Delete(0, Interval::new(3, 4)),
AssertOpsJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
AssertDocJson(
0,
r#"[{"insert":"123456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);

View File

@ -45,6 +45,9 @@ pub enum TestOp {
#[display(fmt = "Transform")]
Transform(usize, usize),
#[display(fmt = "TransformPrime")]
TransformPrime(usize, usize),
// invert the delta_a base on the delta_b
#[display(fmt = "Invert")]
Invert(usize, usize),
@ -61,12 +64,23 @@ pub enum TestOp {
#[display(fmt = "AssertStr")]
AssertStr(usize, &'static str),
#[display(fmt = "AssertOpsJson")]
AssertOpsJson(usize, &'static str),
#[display(fmt = "AssertDocJson")]
AssertDocJson(usize, &'static str),
#[display(fmt = "AssertPrimeJson")]
AssertPrimeJson(usize, &'static str),
#[display(fmt = "DocComposeDelta")]
DocComposeDelta(usize, usize),
#[display(fmt = "ApplyPrimeDelta")]
DocComposePrime(usize, usize),
}
pub struct TestBuilder {
documents: Vec<Document>,
deltas: Vec<Option<Delta>>,
primes: Vec<Option<Delta>>,
}
impl TestBuilder {
@ -78,7 +92,11 @@ impl TestBuilder {
env_logger::init();
});
Self { documents: vec![] }
Self {
documents: vec![],
deltas: vec![],
primes: vec![],
}
}
fn run_op(&mut self, op: &TestOp) {
@ -86,15 +104,18 @@ impl TestBuilder {
match op {
TestOp::Insert(delta_i, s, index) => {
let document = &mut self.documents[*delta_i];
document.insert(*index, s).unwrap();
let delta = document.insert(*index, s).unwrap();
self.deltas.insert(*delta_i, Some(delta));
},
TestOp::Delete(delta_i, iv) => {
let document = &mut self.documents[*delta_i];
document.replace(*iv, "").unwrap();
let delta = document.replace(*iv, "").unwrap();
self.deltas.insert(*delta_i, Some(delta));
},
TestOp::Replace(delta_i, iv, s) => {
let document = &mut self.documents[*delta_i];
document.replace(*iv, s).unwrap();
let delta = document.replace(*iv, s).unwrap();
self.deltas.insert(*delta_i, Some(delta));
},
TestOp::InsertBold(delta_i, s, iv) => {
let document = &mut self.documents[*delta_i];
@ -104,7 +125,8 @@ impl TestBuilder {
TestOp::Bold(delta_i, iv, enable) => {
let document = &mut self.documents[*delta_i];
let attribute = Attribute::Bold(*enable);
document.format(*iv, attribute).unwrap();
let delta = document.format(*iv, attribute).unwrap();
self.deltas.insert(*delta_i, Some(delta));
},
TestOp::Italic(delta_i, iv, enable) => {
let document = &mut self.documents[*delta_i];
@ -112,22 +134,26 @@ impl TestBuilder {
true => Attribute::Italic(true),
false => Attribute::Italic(false),
};
document.format(*iv, attribute).unwrap();
let delta = document.format(*iv, attribute).unwrap();
self.deltas.insert(*delta_i, Some(delta));
},
TestOp::Header(delta_i, iv, level) => {
let document = &mut self.documents[*delta_i];
let attribute = Attribute::Header(*level);
document.format(*iv, attribute).unwrap();
let delta = document.format(*iv, attribute).unwrap();
self.deltas.insert(*delta_i, Some(delta));
},
TestOp::Link(delta_i, iv, link) => {
let document = &mut self.documents[*delta_i];
let attribute = Attribute::Link(link.to_owned());
document.format(*iv, attribute).unwrap();
let delta = document.format(*iv, attribute).unwrap();
self.deltas.insert(*delta_i, Some(delta));
},
TestOp::Bullet(delta_i, iv, enable) => {
let document = &mut self.documents[*delta_i];
let attribute = Attribute::Bullet(*enable);
document.format(*iv, attribute).unwrap();
let delta = document.format(*iv, attribute).unwrap();
self.deltas.insert(*delta_i, Some(delta));
},
TestOp::Transform(delta_a_i, delta_b_i) => {
let (a_prime, b_prime) = self.documents[*delta_a_i]
@ -142,6 +168,15 @@ impl TestBuilder {
self.documents[*delta_a_i].set_delta(data_left);
self.documents[*delta_b_i].set_delta(data_right);
},
TestOp::TransformPrime(a_doc_index, b_doc_index) => {
let (prime_left, prime_right) = self.documents[*a_doc_index]
.delta()
.transform(&self.documents[*b_doc_index].delta())
.unwrap();
self.primes.insert(*a_doc_index, Some(prime_left));
self.primes.insert(*b_doc_index, Some(prime_right));
},
TestOp::Invert(delta_a_i, delta_b_i) => {
let delta_a = &self.documents[*delta_a_i].delta();
let delta_b = &self.documents[*delta_b_i].delta();
@ -177,22 +212,50 @@ impl TestBuilder {
assert_eq!(&self.documents[*delta_i].to_plain_string(), expected);
},
TestOp::AssertOpsJson(delta_i, expected) => {
let delta_i_json = self.documents[*delta_i].to_json();
TestOp::AssertDocJson(delta_i, expected) => {
let delta_json = self.documents[*delta_i].to_json();
let expected_delta: Delta = serde_json::from_str(expected).unwrap();
let target_delta: Delta = serde_json::from_str(&delta_i_json).unwrap();
let target_delta: Delta = serde_json::from_str(&delta_json).unwrap();
if expected_delta != target_delta {
log::error!("✅ expect: {}", expected,);
log::error!("❌ receive: {}", delta_i_json);
log::error!("❌ receive: {}", delta_json);
}
assert_eq!(target_delta, expected_delta);
},
TestOp::AssertPrimeJson(doc_i, expected) => {
let prime_json = self.primes[*doc_i].as_ref().unwrap().to_json();
let expected_prime: Delta = serde_json::from_str(expected).unwrap();
let target_prime: Delta = serde_json::from_str(&prime_json).unwrap();
if expected_prime != target_prime {
log::error!("✅ expect prime: {}", expected,);
log::error!("❌ receive prime: {}", prime_json);
}
assert_eq!(target_prime, expected_prime);
},
TestOp::DocComposeDelta(doc_index, delta_i) => {
let delta = self.deltas.get(*delta_i).unwrap().as_ref().unwrap();
self.documents[*doc_index].compose_delta(delta);
},
TestOp::DocComposePrime(doc_index, prime_i) => {
let delta = self
.primes
.get(*prime_i)
.expect("Must call TransformPrime first")
.as_ref()
.unwrap();
let new_delta = self.documents[*doc_index].delta().compose(delta).unwrap();
self.documents[*doc_index].set_delta(new_delta);
},
}
}
pub fn run_script<C: CustomDocument>(mut self, script: Vec<TestOp>) {
self.documents = vec![Document::new::<C>(), Document::new::<C>()];
self.primes = vec![None, None];
self.deltas = vec![None, None];
for (_i, op) in script.iter().enumerate() {
self.run_op(op);
}

View File

@ -8,7 +8,7 @@ fn attributes_insert_text() {
let ops = vec![
Insert(0, "123", 0),
Insert(0, "456", 3),
AssertOpsJson(0, r#"[{"insert":"123456"}]"#),
AssertDocJson(0, r#"[{"insert":"123456"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -18,7 +18,7 @@ fn attributes_insert_text_at_head() {
let ops = vec![
Insert(0, "123", 0),
Insert(0, "456", 0),
AssertOpsJson(0, r#"[{"insert":"456123"}]"#),
AssertDocJson(0, r#"[{"insert":"456123"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -28,7 +28,7 @@ fn attributes_insert_text_at_middle() {
let ops = vec![
Insert(0, "123", 0),
Insert(0, "456", 1),
AssertOpsJson(0, r#"[{"insert":"145623"}]"#),
AssertDocJson(0, r#"[{"insert":"145623"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -69,7 +69,10 @@ fn delta_get_ops_in_interval_2() {
vec![OpBuilder::insert("23").build()]
);
assert_eq!(DeltaIter::from_interval(&delta, Interval::new(0, 3)).ops(), vec![insert_a.clone()]);
assert_eq!(
DeltaIter::from_interval(&delta, Interval::new(0, 3)).ops(),
vec![insert_a.clone()]
);
assert_eq!(
DeltaIter::from_interval(&delta, Interval::new(0, 4)).ops(),
@ -109,9 +112,18 @@ fn delta_get_ops_in_interval_4() {
delta.ops.push(insert_b.clone());
delta.ops.push(insert_c.clone());
assert_eq!(DeltaIter::from_interval(&delta, Interval::new(0, 2)).ops(), vec![insert_a]);
assert_eq!(DeltaIter::from_interval(&delta, Interval::new(2, 4)).ops(), vec![insert_b]);
assert_eq!(DeltaIter::from_interval(&delta, Interval::new(4, 6)).ops(), vec![insert_c]);
assert_eq!(
DeltaIter::from_interval(&delta, Interval::new(0, 2)).ops(),
vec![insert_a]
);
assert_eq!(
DeltaIter::from_interval(&delta, Interval::new(2, 4)).ops(),
vec![insert_b]
);
assert_eq!(
DeltaIter::from_interval(&delta, Interval::new(4, 6)).ops(),
vec![insert_c]
);
assert_eq!(
DeltaIter::from_interval(&delta, Interval::new(2, 5)).ops(),
@ -443,7 +455,7 @@ fn compose() {
}
}
#[test]
fn transform() {
fn transform_random_delta() {
for _ in 0..1000 {
let mut rng = Rng::default();
let s = rng.gen_string(20);
@ -461,19 +473,7 @@ fn transform() {
}
#[test]
fn transform2() {
let ops = vec![
Insert(0, "123", 0),
Insert(1, "456", 0),
Transform(0, 1),
AssertOpsJson(0, r#"[{"insert":"123456"}]"#),
AssertOpsJson(1, r#"[{"insert":"123456"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
#[test]
fn delta_transform_test() {
fn transform_with_two_delta_test() {
let mut a = Delta::default();
let mut a_s = String::new();
a.insert("123", AttributeBuilder::new().add(Attribute::Bold(true)).build());
@ -509,6 +509,65 @@ fn delta_transform_test() {
);
}
#[test]
fn transform_two_plain_delta_test() {
let ops = vec![
Insert(0, "123", 0),
Insert(1, "456", 0),
Transform(0, 1),
AssertDocJson(0, r#"[{"insert":"123456"}]"#),
AssertDocJson(1, r#"[{"insert":"123456"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
#[test]
fn transform_two_plain_delta_test2() {
let ops = vec![
Insert(0, "123", 0),
Insert(1, "456", 0),
TransformPrime(0, 1),
DocComposePrime(0, 1),
DocComposePrime(1, 0),
AssertDocJson(0, r#"[{"insert":"123456"}]"#),
AssertDocJson(1, r#"[{"insert":"123456"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
#[test]
fn transform_two_non_seq_delta() {
let ops = vec![
Insert(0, "123", 0),
Insert(1, "456", 0),
TransformPrime(0, 1),
AssertPrimeJson(0, r#"[{"insert":"123"},{"retain":3}]"#),
AssertPrimeJson(1, r#"[{"retain":3},{"insert":"456"}]"#),
DocComposePrime(0, 1),
Insert(1, "78", 3),
Insert(1, "9", 5),
DocComposePrime(1, 0),
AssertDocJson(0, r#"[{"insert":"123456"}]"#),
AssertDocJson(1, r#"[{"insert":"123456789"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
#[test]
fn transform_two_conflict_non_seq_delta() {
let ops = vec![
Insert(0, "123", 0),
Insert(1, "456", 0),
TransformPrime(0, 1),
DocComposePrime(0, 1),
Insert(1, "78", 0),
DocComposePrime(1, 0),
AssertDocJson(0, r#"[{"insert":"123456"}]"#),
AssertDocJson(1, r#"[{"insert":"12378456"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
#[test]
fn delta_invert_no_attribute_delta() {
let mut delta = Delta::default();
@ -531,7 +590,7 @@ fn delta_invert_no_attribute_delta2() {
Insert(0, "123", 0),
Insert(1, "4567", 0),
Invert(0, 1),
AssertOpsJson(0, r#"[{"insert":"123"}]"#),
AssertDocJson(0, r#"[{"insert":"123"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -541,10 +600,10 @@ fn delta_invert_attribute_delta_with_no_attribute_delta() {
let ops = vec![
Insert(0, "123", 0),
Bold(0, Interval::new(0, 3), true),
AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
Insert(1, "4567", 0),
Invert(0, 1),
AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -555,14 +614,14 @@ fn delta_invert_attribute_delta_with_no_attribute_delta2() {
Insert(0, "123", 0),
Bold(0, Interval::new(0, 3), true),
Insert(0, "456", 3),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"123456","attributes":{"bold":"true"}}]
"#,
),
Italic(0, Interval::new(2, 4), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12","attributes":{"bold":"true"}},
@ -572,7 +631,7 @@ fn delta_invert_attribute_delta_with_no_attribute_delta2() {
),
Insert(1, "abc", 0),
Invert(0, 1),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12","attributes":{"bold":"true"}},
@ -590,9 +649,9 @@ fn delta_invert_no_attribute_delta_with_attribute_delta() {
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"}]"#),
AssertDocJson(1, r#"[{"insert":"456","attributes":{"bold":"true"}},{"insert":"7"}]"#),
Invert(0, 1),
AssertOpsJson(0, r#"[{"insert":"123"}]"#),
AssertDocJson(0, r#"[{"insert":"123"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -601,19 +660,17 @@ fn delta_invert_no_attribute_delta_with_attribute_delta() {
fn delta_invert_no_attribute_delta_with_attribute_delta2() {
let ops = vec![
Insert(0, "123", 0),
AssertOpsJson(0, r#"[{"insert":"123"}]"#),
AssertDocJson(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(
AssertDocJson(
1,
r#"[{"insert":"a","attributes":{"bold":"true"}},{"insert":"bc","attributes":
{"bold":"true","italic":"true"}},{"insert":"d","attributes":{"bold":"true"
}}]"#,
r#"[{"insert":"a","attributes":{"bold":"true"}},{"insert":"bc","attributes":{"bold":"true","italic":"true"}},{"insert":"d","attributes":{"bold":"true"}}]"#,
),
Invert(0, 1),
AssertOpsJson(0, r#"[{"insert":"123"}]"#),
AssertDocJson(0, r#"[{"insert":"123"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -624,9 +681,9 @@ fn delta_invert_attribute_delta_with_attribute_delta() {
Insert(0, "123", 0),
Bold(0, Interval::new(0, 3), true),
Insert(0, "456", 3),
AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
Italic(0, Interval::new(2, 4), true),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12","attributes":{"bold":"true"}},
@ -638,7 +695,7 @@ fn delta_invert_attribute_delta_with_attribute_delta() {
Bold(1, Interval::new(0, 3), true),
Insert(1, "d", 3),
Italic(1, Interval::new(1, 3), true),
AssertOpsJson(
AssertDocJson(
1,
r#"[
{"insert":"a","attributes":{"bold":"true"}},
@ -647,7 +704,7 @@ fn delta_invert_attribute_delta_with_attribute_delta() {
]"#,
),
Invert(0, 1),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"12","attributes":{"bold":"true"}},

View File

@ -4,7 +4,7 @@ use flowy_ot::core::{Interval, NEW_LINE, WHITESPACE};
#[test]
fn history_insert_undo() {
let ops = vec![Insert(0, "123", 0), Undo(0), AssertOpsJson(0, r#"[{"insert":"\n"}]"#)];
let ops = vec![Insert(0, "123", 0), Undo(0), AssertDocJson(0, r#"[{"insert":"\n"}]"#)];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -15,9 +15,9 @@ fn history_insert_undo_with_lagging() {
Wait(RECORD_THRESHOLD),
Insert(0, "456", 0),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123\n"}]"#),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -26,11 +26,11 @@ fn history_insert_undo_with_lagging() {
fn history_insert_redo() {
let ops = vec![
Insert(0, "123", 0),
AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123\n"}]"#),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
Redo(0),
AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -43,13 +43,13 @@ fn history_insert_redo_with_lagging() {
Insert(0, "456", 3),
Wait(RECORD_THRESHOLD),
AssertStr(0, "123456\n"),
AssertOpsJson(0, r#"[{"insert":"123456\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123456\n"}]"#),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123\n"}]"#),
Redo(0),
AssertOpsJson(0, r#"[{"insert":"123456\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123456\n"}]"#),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -60,7 +60,7 @@ fn history_bold_undo() {
Insert(0, "123", 0),
Bold(0, Interval::new(0, 3), true),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -72,7 +72,7 @@ fn history_bold_undo_with_lagging() {
Wait(RECORD_THRESHOLD),
Bold(0, Interval::new(0, 3), true),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -83,9 +83,9 @@ fn history_bold_redo() {
Insert(0, "123", 0),
Bold(0, Interval::new(0, 3), true),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
Redo(0),
AssertOpsJson(0, r#" [{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
AssertDocJson(0, r#" [{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -97,9 +97,9 @@ fn history_bold_redo_with_lagging() {
Wait(RECORD_THRESHOLD),
Bold(0, Interval::new(0, 3), true),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123\n"}]"#),
Redo(0),
AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -108,11 +108,11 @@ fn history_bold_redo_with_lagging() {
fn history_delete_undo() {
let ops = vec![
Insert(0, "123", 0),
AssertOpsJson(0, r#"[{"insert":"123"}]"#),
AssertDocJson(0, r#"[{"insert":"123"}]"#),
Delete(0, Interval::new(0, 3)),
AssertOpsJson(0, r#"[]"#),
AssertDocJson(0, r#"[]"#),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"123"}]"#),
AssertDocJson(0, r#"[{"insert":"123"}]"#),
];
TestBuilder::new().run_script::<PlainDoc>(ops);
}
@ -123,7 +123,7 @@ fn history_delete_undo_2() {
Insert(0, "123", 0),
Bold(0, Interval::new(0, 3), true),
Delete(0, Interval::new(0, 1)),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"23","attributes":{"bold":"true"}},
@ -131,7 +131,7 @@ fn history_delete_undo_2() {
"#,
),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -144,7 +144,7 @@ fn history_delete_undo_with_lagging() {
Bold(0, Interval::new(0, 3), true),
Wait(RECORD_THRESHOLD),
Delete(0, Interval::new(0, 1)),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"23","attributes":{"bold":"true"}},
@ -152,7 +152,7 @@ fn history_delete_undo_with_lagging() {
"#,
),
Undo(0),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"123","attributes":{"bold":"true"}},
@ -169,10 +169,10 @@ fn history_delete_redo() {
Insert(0, "123", 0),
Wait(RECORD_THRESHOLD),
Delete(0, Interval::new(0, 3)),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
Undo(0),
Redo(0),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -183,7 +183,7 @@ fn history_replace_undo() {
Insert(0, "123", 0),
Bold(0, Interval::new(0, 3), true),
Replace(0, Interval::new(0, 2), "ab"),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"ab"},
@ -191,7 +191,7 @@ fn history_replace_undo() {
"#,
),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -204,7 +204,7 @@ fn history_replace_undo_with_lagging() {
Bold(0, Interval::new(0, 3), true),
Wait(RECORD_THRESHOLD),
Replace(0, Interval::new(0, 2), "ab"),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"ab"},
@ -212,7 +212,7 @@ fn history_replace_undo_with_lagging() {
"#,
),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
}
@ -225,7 +225,7 @@ fn history_replace_redo() {
Replace(0, Interval::new(0, 2), "ab"),
Undo(0),
Redo(0),
AssertOpsJson(
AssertDocJson(
0,
r#"[
{"insert":"ab"},
@ -244,9 +244,9 @@ fn history_header_added_undo() {
Insert(0, "\n", 3),
Insert(0, "\n", 4),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
Redo(0),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123"},{"insert":"\n\n","attributes":{"header":1}},{"insert":"456"},{"insert":"\n","attributes":{"header":1}}]"#,
),
@ -263,9 +263,9 @@ fn history_link_added_undo() {
Wait(RECORD_THRESHOLD),
Link(0, Interval::new(0, site.len()), site),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
AssertDocJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
Redo(0),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"https://appflowy.io","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
),
@ -279,15 +279,15 @@ fn history_link_auto_format_undo_with_lagging() {
let site = "https://appflowy.io";
let ops = vec![
Insert(0, site, 0),
AssertOpsJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
AssertDocJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
Wait(RECORD_THRESHOLD),
Insert(0, WHITESPACE, site.len()),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"https://appflowy.io","attributes":{"link":"https://appflowy.io/"}},{"insert":" \n"}]"#,
),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
AssertDocJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
];
TestBuilder::new().run_script::<FlowyDoc>(ops);
@ -300,14 +300,14 @@ fn history_bullet_undo() {
Bullet(0, Interval::new(0, 1), true),
Insert(0, NEW_LINE, 1),
Insert(0, "2", 2),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
Redo(0),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
),
@ -325,17 +325,17 @@ fn history_bullet_undo_with_lagging() {
Insert(0, NEW_LINE, 1),
Insert(0, "2", 2),
Wait(RECORD_THRESHOLD),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
AssertDocJson(0, r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
Undo(0),
AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
AssertDocJson(0, r#"[{"insert":"\n"}]"#),
Redo(0),
Redo(0),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
),
@ -352,14 +352,17 @@ fn history_undo_attribute_on_merge_between_line() {
Wait(RECORD_THRESHOLD),
Insert(0, NEW_LINE, 3),
Wait(RECORD_THRESHOLD),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
),
Delete(0, Interval::new(3, 4)), // delete the newline
AssertOpsJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
AssertDocJson(
0,
r#"[{"insert":"123456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
),
Undo(0),
AssertOpsJson(
AssertDocJson(
0,
r#"[{"insert":"123"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
),

View File

@ -48,10 +48,7 @@ impl std::convert::TryFrom<Vec<u8>> for Delta {
impl std::convert::TryFrom<Bytes> for Delta {
type Error = OTError;
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
let bytes = value.to_vec();
Delta::from_bytes(bytes)
}
fn try_from(bytes: Bytes) -> Result<Self, Self::Error> { Delta::from_bytes(&bytes) }
}
// impl<T: AsRef<Vec<u8>>> std::convert::From<T> for Delta {
@ -94,8 +91,8 @@ impl Delta {
pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap_or("".to_owned()) }
pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, OTError> {
let json = str::from_utf8(&bytes)?;
pub fn from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, OTError> {
let json = str::from_utf8(bytes.as_ref())?;
Self::from_json(json)
}
@ -271,8 +268,12 @@ impl OperationTransformable for Delta {
other_iter.next_op_len().unwrap_or(MAX_IV_LEN),
);
let op = iter.next_op_with_len(length).unwrap_or(OpBuilder::retain(length).build());
let other_op = other_iter.next_op_with_len(length).unwrap_or(OpBuilder::retain(length).build());
let op = iter
.next_op_with_len(length)
.unwrap_or(OpBuilder::retain(length).build());
let other_op = other_iter
.next_op_with_len(length)
.unwrap_or(OpBuilder::retain(length).build());
debug_assert_eq!(op.len(), other_op.len());

View File

@ -65,10 +65,11 @@ pub struct CreateViewParams {
pub view_type: ViewType,
#[pb(index = 6)]
pub data: Vec<u8>,
pub data: String,
}
const VIEW_DEFAULT_DATA: &str = "[{\"insert\":\"\\n\"}]";
pub const VIEW_DEFAULT_DATA: &str = "[{\"insert\":\"\\n\"}]";
#[allow(dead_code)]
pub fn default_delta() -> Vec<u8> { VIEW_DEFAULT_DATA.as_bytes().to_vec() }
impl CreateViewParams {
@ -79,7 +80,7 @@ impl CreateViewParams {
desc,
thumbnail,
view_type,
data: default_delta(),
data: VIEW_DEFAULT_DATA.to_string(),
}
}
}
@ -88,9 +89,13 @@ impl TryInto<CreateViewParams> for CreateViewRequest {
type Error = WorkspaceError;
fn try_into(self) -> Result<CreateViewParams, Self::Error> {
let name = ViewName::parse(self.name).map_err(|e| WorkspaceError::view_name().context(e))?.0;
let name = ViewName::parse(self.name)
.map_err(|e| WorkspaceError::view_name().context(e))?
.0;
let belong_to_id = AppId::parse(self.belong_to_id).map_err(|e| WorkspaceError::app_id().context(e))?.0;
let belong_to_id = AppId::parse(self.belong_to_id)
.map_err(|e| WorkspaceError::app_id().context(e))?
.0;
let thumbnail = match self.thumbnail {
None => "".to_string(),
@ -101,7 +106,13 @@ impl TryInto<CreateViewParams> for CreateViewRequest {
},
};
Ok(CreateViewParams::new(belong_to_id, name, self.desc, self.view_type, thumbnail))
Ok(CreateViewParams::new(
belong_to_id,
name,
self.desc,
self.view_type,
thumbnail,
))
}
}

View File

@ -3,7 +3,7 @@ use crate::{
errors::WorkspaceError,
};
use flowy_derive::ProtoBuf;
use flowy_document::entities::doc::DocDelta;
use std::convert::TryInto;
#[derive(Default, ProtoBuf)]
@ -69,16 +69,26 @@ impl TryInto<UpdateViewParams> for UpdateViewRequest {
type Error = WorkspaceError;
fn try_into(self) -> Result<UpdateViewParams, Self::Error> {
let view_id = ViewId::parse(self.view_id).map_err(|e| WorkspaceError::view_id().context(e))?.0;
let view_id = ViewId::parse(self.view_id)
.map_err(|e| WorkspaceError::view_id().context(e))?
.0;
let name = match self.name {
None => None,
Some(name) => Some(ViewName::parse(name).map_err(|e| WorkspaceError::view_name().context(e))?.0),
Some(name) => Some(
ViewName::parse(name)
.map_err(|e| WorkspaceError::view_name().context(e))?
.0,
),
};
let desc = match self.desc {
None => None,
Some(desc) => Some(ViewDesc::parse(desc).map_err(|e| WorkspaceError::view_desc().context(e))?.0),
Some(desc) => Some(
ViewDesc::parse(desc)
.map_err(|e| WorkspaceError::view_desc().context(e))?
.0,
),
};
let thumbnail = match self.thumbnail {
@ -99,25 +109,23 @@ impl TryInto<UpdateViewParams> for UpdateViewRequest {
})
}
}
#[derive(Default, ProtoBuf)]
pub struct ApplyChangesetRequest {
#[pb(index = 1)]
pub view_id: String,
#[pb(index = 2)]
pub data: Vec<u8>,
}
impl TryInto<DocDelta> for ApplyChangesetRequest {
type Error = WorkspaceError;
fn try_into(self) -> Result<DocDelta, Self::Error> {
let view_id = ViewId::parse(self.view_id).map_err(|e| WorkspaceError::view_id().context(e))?.0;
// Opti: Vec<u8> -> Delta -> Vec<u8>
let data = DeltaData::parse(self.data).map_err(|e| WorkspaceError::view_data().context(e))?.0;
Ok(DocDelta { doc_id: view_id, data })
}
}
// #[derive(Default, ProtoBuf)]
// pub struct DocDeltaRequest {
// #[pb(index = 1)]
// pub view_id: String,
//
// #[pb(index = 2)]
// pub data: String,
// }
//
// impl TryInto<DocDelta> for DocDeltaRequest {
// type Error = WorkspaceError;
//
// fn try_into(self) -> Result<DocDelta, Self::Error> {
// let view_id = ViewId::parse(self.view_id)
// .map_err(|e| WorkspaceError::view_id().context(e))?
// .0;
//
// Ok(DocDelta { doc_id: view_id, data: self.data })
// }
// }

View File

@ -1,6 +1,5 @@
use crate::{
entities::view::{
ApplyChangesetRequest,
CreateViewParams,
CreateViewRequest,
DeleteViewParams,
@ -57,11 +56,11 @@ pub(crate) async fn update_view_handler(
#[tracing::instrument(skip(data, controller), err)]
pub(crate) async fn apply_doc_delta_handler(
data: Data<ApplyChangesetRequest>,
data: Data<DocDelta>,
controller: Unit<Arc<ViewController>>,
) -> DataResult<Doc, WorkspaceError> {
let params: DocDelta = data.into_inner().try_into()?;
let doc = controller.apply_doc_delta(params).await?;
// let params: DocDelta = data.into_inner().try_into()?;
let doc = controller.apply_doc_delta(data.into_inner()).await?;
data_result(doc)
}

View File

@ -387,7 +387,7 @@ pub struct CreateViewParams {
pub desc: ::std::string::String,
pub thumbnail: ::std::string::String,
pub view_type: ViewType,
pub data: ::std::vec::Vec<u8>,
pub data: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
@ -523,10 +523,10 @@ impl CreateViewParams {
self.view_type = v;
}
// bytes data = 6;
// string data = 6;
pub fn get_data(&self) -> &[u8] {
pub fn get_data(&self) -> &str {
&self.data
}
pub fn clear_data(&mut self) {
@ -534,19 +534,19 @@ impl CreateViewParams {
}
// Param is passed by value, moved
pub fn set_data(&mut self, v: ::std::vec::Vec<u8>) {
pub fn set_data(&mut self, v: ::std::string::String) {
self.data = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_data(&mut self) -> &mut ::std::vec::Vec<u8> {
pub fn mut_data(&mut self) -> &mut ::std::string::String {
&mut self.data
}
// Take field
pub fn take_data(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.data, ::std::vec::Vec::new())
pub fn take_data(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.data, ::std::string::String::new())
}
}
@ -575,7 +575,7 @@ impl ::protobuf::Message for CreateViewParams {
::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.view_type, 5, &mut self.unknown_fields)?
},
6 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?;
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@ -605,7 +605,7 @@ impl ::protobuf::Message for CreateViewParams {
my_size += ::protobuf::rt::enum_size(5, self.view_type);
}
if !self.data.is_empty() {
my_size += ::protobuf::rt::bytes_size(6, &self.data);
my_size += ::protobuf::rt::string_size(6, &self.data);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
@ -629,7 +629,7 @@ impl ::protobuf::Message for CreateViewParams {
os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?;
}
if !self.data.is_empty() {
os.write_bytes(6, &self.data)?;
os.write_string(6, &self.data)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
@ -694,7 +694,7 @@ impl ::protobuf::Message for CreateViewParams {
|m: &CreateViewParams| { &m.view_type },
|m: &mut CreateViewParams| { &mut m.view_type },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"data",
|m: &CreateViewParams| { &m.data },
|m: &mut CreateViewParams| { &mut m.data },
@ -1441,7 +1441,7 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\nbelongToId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04\
desc\x18\x03\x20\x01(\tR\x04desc\x12\x1c\n\tthumbnail\x18\x04\x20\x01(\t\
R\tthumbnail\x12&\n\tview_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08view\
Type\x12\x12\n\x04data\x18\x06\x20\x01(\x0cR\x04data\"\x97\x02\n\x04View\
Type\x12\x12\n\x04data\x18\x06\x20\x01(\tR\x04data\"\x97\x02\n\x04View\
\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x20\n\x0cbelong_to_id\x18\
\x02\x20\x01(\tR\nbelongToId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04na\
me\x12\x12\n\x04desc\x18\x04\x20\x01(\tR\x04desc\x12&\n\tview_type\x18\
@ -1483,9 +1483,9 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x12\x03\x0e\x04\x1b\n\x0c\n\x05\x04\x01\x02\x04\x06\x12\x03\x0e\x04\x0c\
\n\x0c\n\x05\x04\x01\x02\x04\x01\x12\x03\x0e\r\x16\n\x0c\n\x05\x04\x01\
\x02\x04\x03\x12\x03\x0e\x19\x1a\n\x0b\n\x04\x04\x01\x02\x05\x12\x03\x0f\
\x04\x13\n\x0c\n\x05\x04\x01\x02\x05\x05\x12\x03\x0f\x04\t\n\x0c\n\x05\
\x04\x01\x02\x05\x01\x12\x03\x0f\n\x0e\n\x0c\n\x05\x04\x01\x02\x05\x03\
\x12\x03\x0f\x11\x12\n\n\n\x02\x04\x02\x12\x04\x11\0\x1b\x01\n\n\n\x03\
\x04\x14\n\x0c\n\x05\x04\x01\x02\x05\x05\x12\x03\x0f\x04\n\n\x0c\n\x05\
\x04\x01\x02\x05\x01\x12\x03\x0f\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x05\x03\
\x12\x03\x0f\x12\x13\n\n\n\x02\x04\x02\x12\x04\x11\0\x1b\x01\n\n\n\x03\
\x04\x02\x01\x12\x03\x11\x08\x0c\n\x0b\n\x04\x04\x02\x02\0\x12\x03\x12\
\x04\x12\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x12\x04\n\n\x0c\n\x05\x04\
\x02\x02\0\x01\x12\x03\x12\x0b\r\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\

View File

@ -944,7 +944,7 @@ impl ::protobuf::reflect::ProtobufValue for UpdateViewParams {
}
#[derive(PartialEq,Clone,Default)]
pub struct ApplyChangesetRequest {
pub struct DocDeltaRequest {
// message fields
pub view_id: ::std::string::String,
pub data: ::std::vec::Vec<u8>,
@ -953,14 +953,14 @@ pub struct ApplyChangesetRequest {
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a ApplyChangesetRequest {
fn default() -> &'a ApplyChangesetRequest {
<ApplyChangesetRequest as ::protobuf::Message>::default_instance()
impl<'a> ::std::default::Default for &'a DocDeltaRequest {
fn default() -> &'a DocDeltaRequest {
<DocDeltaRequest as ::protobuf::Message>::default_instance()
}
}
impl ApplyChangesetRequest {
pub fn new() -> ApplyChangesetRequest {
impl DocDeltaRequest {
pub fn new() -> DocDeltaRequest {
::std::default::Default::default()
}
@ -1017,7 +1017,7 @@ impl ApplyChangesetRequest {
}
}
impl ::protobuf::Message for ApplyChangesetRequest {
impl ::protobuf::Message for DocDeltaRequest {
fn is_initialized(&self) -> bool {
true
}
@ -1092,8 +1092,8 @@ impl ::protobuf::Message for ApplyChangesetRequest {
Self::descriptor_static()
}
fn new() -> ApplyChangesetRequest {
ApplyChangesetRequest::new()
fn new() -> DocDeltaRequest {
DocDeltaRequest::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
@ -1102,29 +1102,29 @@ impl ::protobuf::Message for ApplyChangesetRequest {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"view_id",
|m: &ApplyChangesetRequest| { &m.view_id },
|m: &mut ApplyChangesetRequest| { &mut m.view_id },
|m: &DocDeltaRequest| { &m.view_id },
|m: &mut DocDeltaRequest| { &mut m.view_id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
"data",
|m: &ApplyChangesetRequest| { &m.data },
|m: &mut ApplyChangesetRequest| { &mut m.data },
|m: &DocDeltaRequest| { &m.data },
|m: &mut DocDeltaRequest| { &mut m.data },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<ApplyChangesetRequest>(
"ApplyChangesetRequest",
::protobuf::reflect::MessageDescriptor::new_pb_name::<DocDeltaRequest>(
"DocDeltaRequest",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static ApplyChangesetRequest {
static instance: ::protobuf::rt::LazyV2<ApplyChangesetRequest> = ::protobuf::rt::LazyV2::INIT;
instance.get(ApplyChangesetRequest::new)
fn default_instance() -> &'static DocDeltaRequest {
static instance: ::protobuf::rt::LazyV2<DocDeltaRequest> = ::protobuf::rt::LazyV2::INIT;
instance.get(DocDeltaRequest::new)
}
}
impl ::protobuf::Clear for ApplyChangesetRequest {
impl ::protobuf::Clear for DocDeltaRequest {
fn clear(&mut self) {
self.view_id.clear();
self.data.clear();
@ -1132,13 +1132,13 @@ impl ::protobuf::Clear for ApplyChangesetRequest {
}
}
impl ::std::fmt::Debug for ApplyChangesetRequest {
impl ::std::fmt::Debug for DocDeltaRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for ApplyChangesetRequest {
impl ::protobuf::reflect::ProtobufValue for DocDeltaRequest {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
@ -1156,55 +1156,55 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\
\x02R\tthumbnail\x12\x1b\n\x08is_trash\x18\x05\x20\x01(\x08H\x03R\x07isT\
rashB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnailB\
\x11\n\x0fone_of_is_trash\"D\n\x15ApplyChangesetRequest\x12\x17\n\x07vie\
w_id\x18\x01\x20\x01(\tR\x06viewId\x12\x12\n\x04data\x18\x02\x20\x01(\
\x0cR\x04dataJ\xc6\x07\n\x06\x12\x04\0\0\x13\x01\n\x08\n\x01\x0c\x12\x03\
\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x08\x01\n\n\n\x03\x04\0\x01\x12\
\x03\x02\x08\x19\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x17\n\x0c\n\x05\
\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\
\x03\x0b\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x15\x16\n\x0b\n\x04\
\x04\0\x08\0\x12\x03\x04\x04*\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\x04\n\
\x15\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x18(\n\x0c\n\x05\x04\0\x02\
\x01\x05\x12\x03\x04\x18\x1e\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\
\x1f#\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04&'\n\x0b\n\x04\x04\0\x08\
\x01\x12\x03\x05\x04*\n\x0c\n\x05\x04\0\x08\x01\x01\x12\x03\x05\n\x15\n\
\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x18(\n\x0c\n\x05\x04\0\x02\x02\x05\
\x12\x03\x05\x18\x1e\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x1f#\n\
\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05&'\n\x0b\n\x04\x04\0\x08\x02\x12\
\x03\x06\x044\n\x0c\n\x05\x04\0\x08\x02\x01\x12\x03\x06\n\x1a\n\x0b\n\
\x04\x04\0\x02\x03\x12\x03\x06\x1d2\n\x0c\n\x05\x04\0\x02\x03\x05\x12\
\x03\x06\x1d#\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06$-\n\x0c\n\x05\
\x04\0\x02\x03\x03\x12\x03\x0601\n\x0b\n\x04\x04\0\x08\x03\x12\x03\x07\
\x040\n\x0c\n\x05\x04\0\x08\x03\x01\x12\x03\x07\n\x19\n\x0b\n\x04\x04\0\
\x02\x04\x12\x03\x07\x1c.\n\x0c\n\x05\x04\0\x02\x04\x05\x12\x03\x07\x1c\
\x20\n\x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x07!)\n\x0c\n\x05\x04\0\x02\
\x04\x03\x12\x03\x07,-\n\n\n\x02\x04\x01\x12\x04\t\0\x0f\x01\n\n\n\x03\
\x04\x01\x01\x12\x03\t\x08\x18\n\x0b\n\x04\x04\x01\x02\0\x12\x03\n\x04\
\x17\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\
\x02\0\x01\x12\x03\n\x0b\x12\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\n\x15\
\x16\n\x0b\n\x04\x04\x01\x08\0\x12\x03\x0b\x04*\n\x0c\n\x05\x04\x01\x08\
\0\x01\x12\x03\x0b\n\x15\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\x0b\x18(\n\
\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x0b\x18\x1e\n\x0c\n\x05\x04\x01\
\x02\x01\x01\x12\x03\x0b\x1f#\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\
\x0b&'\n\x0b\n\x04\x04\x01\x08\x01\x12\x03\x0c\x04*\n\x0c\n\x05\x04\x01\
\x08\x01\x01\x12\x03\x0c\n\x15\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\x0c\
\x18(\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x0c\x18\x1e\n\x0c\n\x05\
\x04\x01\x02\x02\x01\x12\x03\x0c\x1f#\n\x0c\n\x05\x04\x01\x02\x02\x03\
\x12\x03\x0c&'\n\x0b\n\x04\x04\x01\x08\x02\x12\x03\r\x044\n\x0c\n\x05\
\x04\x01\x08\x02\x01\x12\x03\r\n\x1a\n\x0b\n\x04\x04\x01\x02\x03\x12\x03\
\r\x1d2\n\x0c\n\x05\x04\x01\x02\x03\x05\x12\x03\r\x1d#\n\x0c\n\x05\x04\
\x01\x02\x03\x01\x12\x03\r$-\n\x0c\n\x05\x04\x01\x02\x03\x03\x12\x03\r01\
\n\x0b\n\x04\x04\x01\x08\x03\x12\x03\x0e\x040\n\x0c\n\x05\x04\x01\x08\
\x03\x01\x12\x03\x0e\n\x19\n\x0b\n\x04\x04\x01\x02\x04\x12\x03\x0e\x1c.\
\n\x0c\n\x05\x04\x01\x02\x04\x05\x12\x03\x0e\x1c\x20\n\x0c\n\x05\x04\x01\
\x02\x04\x01\x12\x03\x0e!)\n\x0c\n\x05\x04\x01\x02\x04\x03\x12\x03\x0e,-\
\n\n\n\x02\x04\x02\x12\x04\x10\0\x13\x01\n\n\n\x03\x04\x02\x01\x12\x03\
\x10\x08\x1d\n\x0b\n\x04\x04\x02\x02\0\x12\x03\x11\x04\x17\n\x0c\n\x05\
\x04\x02\x02\0\x05\x12\x03\x11\x04\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\
\x03\x11\x0b\x12\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x11\x15\x16\n\x0b\
\n\x04\x04\x02\x02\x01\x12\x03\x12\x04\x13\n\x0c\n\x05\x04\x02\x02\x01\
\x05\x12\x03\x12\x04\t\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\x12\n\x0e\
\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\x12\x11\x12b\x06proto3\
\x11\n\x0fone_of_is_trash\">\n\x0fDocDeltaRequest\x12\x17\n\x07view_id\
\x18\x01\x20\x01(\tR\x06viewId\x12\x12\n\x04data\x18\x02\x20\x01(\x0cR\
\x04dataJ\xc6\x07\n\x06\x12\x04\0\0\x13\x01\n\x08\n\x01\x0c\x12\x03\0\0\
\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x08\x01\n\n\n\x03\x04\0\x01\x12\x03\
\x02\x08\x19\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x17\n\x0c\n\x05\x04\
\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\
\x0b\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x15\x16\n\x0b\n\x04\x04\
\0\x08\0\x12\x03\x04\x04*\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\x04\n\x15\
\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x18(\n\x0c\n\x05\x04\0\x02\x01\
\x05\x12\x03\x04\x18\x1e\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x1f#\
\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04&'\n\x0b\n\x04\x04\0\x08\x01\
\x12\x03\x05\x04*\n\x0c\n\x05\x04\0\x08\x01\x01\x12\x03\x05\n\x15\n\x0b\
\n\x04\x04\0\x02\x02\x12\x03\x05\x18(\n\x0c\n\x05\x04\0\x02\x02\x05\x12\
\x03\x05\x18\x1e\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x1f#\n\x0c\n\
\x05\x04\0\x02\x02\x03\x12\x03\x05&'\n\x0b\n\x04\x04\0\x08\x02\x12\x03\
\x06\x044\n\x0c\n\x05\x04\0\x08\x02\x01\x12\x03\x06\n\x1a\n\x0b\n\x04\
\x04\0\x02\x03\x12\x03\x06\x1d2\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\
\x06\x1d#\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06$-\n\x0c\n\x05\x04\0\
\x02\x03\x03\x12\x03\x0601\n\x0b\n\x04\x04\0\x08\x03\x12\x03\x07\x040\n\
\x0c\n\x05\x04\0\x08\x03\x01\x12\x03\x07\n\x19\n\x0b\n\x04\x04\0\x02\x04\
\x12\x03\x07\x1c.\n\x0c\n\x05\x04\0\x02\x04\x05\x12\x03\x07\x1c\x20\n\
\x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x07!)\n\x0c\n\x05\x04\0\x02\x04\x03\
\x12\x03\x07,-\n\n\n\x02\x04\x01\x12\x04\t\0\x0f\x01\n\n\n\x03\x04\x01\
\x01\x12\x03\t\x08\x18\n\x0b\n\x04\x04\x01\x02\0\x12\x03\n\x04\x17\n\x0c\
\n\x05\x04\x01\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\
\x12\x03\n\x0b\x12\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\n\x15\x16\n\x0b\
\n\x04\x04\x01\x08\0\x12\x03\x0b\x04*\n\x0c\n\x05\x04\x01\x08\0\x01\x12\
\x03\x0b\n\x15\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\x0b\x18(\n\x0c\n\x05\
\x04\x01\x02\x01\x05\x12\x03\x0b\x18\x1e\n\x0c\n\x05\x04\x01\x02\x01\x01\
\x12\x03\x0b\x1f#\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x0b&'\n\x0b\n\
\x04\x04\x01\x08\x01\x12\x03\x0c\x04*\n\x0c\n\x05\x04\x01\x08\x01\x01\
\x12\x03\x0c\n\x15\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\x0c\x18(\n\x0c\n\
\x05\x04\x01\x02\x02\x05\x12\x03\x0c\x18\x1e\n\x0c\n\x05\x04\x01\x02\x02\
\x01\x12\x03\x0c\x1f#\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\x0c&'\n\
\x0b\n\x04\x04\x01\x08\x02\x12\x03\r\x044\n\x0c\n\x05\x04\x01\x08\x02\
\x01\x12\x03\r\n\x1a\n\x0b\n\x04\x04\x01\x02\x03\x12\x03\r\x1d2\n\x0c\n\
\x05\x04\x01\x02\x03\x05\x12\x03\r\x1d#\n\x0c\n\x05\x04\x01\x02\x03\x01\
\x12\x03\r$-\n\x0c\n\x05\x04\x01\x02\x03\x03\x12\x03\r01\n\x0b\n\x04\x04\
\x01\x08\x03\x12\x03\x0e\x040\n\x0c\n\x05\x04\x01\x08\x03\x01\x12\x03\
\x0e\n\x19\n\x0b\n\x04\x04\x01\x02\x04\x12\x03\x0e\x1c.\n\x0c\n\x05\x04\
\x01\x02\x04\x05\x12\x03\x0e\x1c\x20\n\x0c\n\x05\x04\x01\x02\x04\x01\x12\
\x03\x0e!)\n\x0c\n\x05\x04\x01\x02\x04\x03\x12\x03\x0e,-\n\n\n\x02\x04\
\x02\x12\x04\x10\0\x13\x01\n\n\n\x03\x04\x02\x01\x12\x03\x10\x08\x17\n\
\x0b\n\x04\x04\x02\x02\0\x12\x03\x11\x04\x17\n\x0c\n\x05\x04\x02\x02\0\
\x05\x12\x03\x11\x04\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x11\x0b\x12\
\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x11\x15\x16\n\x0b\n\x04\x04\x02\
\x02\x01\x12\x03\x12\x04\x13\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\x12\
\x04\t\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\x12\n\x0e\n\x0c\n\x05\x04\
\x02\x02\x01\x03\x12\x03\x12\x11\x12b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -13,7 +13,7 @@ message CreateViewParams {
string desc = 3;
string thumbnail = 4;
ViewType view_type = 5;
bytes data = 6;
string data = 6;
}
message View {
string id = 1;

View File

@ -14,7 +14,7 @@ message UpdateViewParams {
oneof one_of_thumbnail { string thumbnail = 4; };
oneof one_of_is_trash { bool is_trash = 5; };
}
message ApplyChangesetRequest {
message DocDeltaRequest {
string view_id = 1;
bytes data = 2;
}

View File

@ -1,5 +1,5 @@
# https://rust-lang.github.io/rustfmt/?version=master&search=
max_width = 140
max_width = 120
tab_spaces = 4
fn_single_line = true
match_block_trailing_comma = true