test event from dart to rust using protobuf as bytes adaptor

This commit is contained in:
appflowy 2021-07-07 22:24:26 +08:00
parent 21b95233fc
commit 2cb26d9e90
44 changed files with 882 additions and 186 deletions

View File

@ -13,8 +13,9 @@ class WelcomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) =>
getIt<WelcomeBloc>()..add(const WelcomeEvent.check()),
create: (context) {
return getIt<WelcomeBloc>()..add(const WelcomeEvent.check());
},
child: Scaffold(
body: BlocListener<WelcomeBloc, WelcomeState>(
listener: (context, state) {

View File

@ -55,11 +55,25 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
logger:
dependency: "direct main"
description:

View File

@ -123,6 +123,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
flutter_test:
dependency: "direct dev"
description: flutter
@ -166,6 +173,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
logger:
dependency: transitive
description:

View File

@ -0,0 +1,33 @@
/// Auto gen code from rust ast, do not edit
part of 'dispatch.dart';
class UserEventSignIn {
UserSignInParams payload;
UserEventSignIn(this.payload);
Future<Either<UserSignInResult, FlowyError>> send() {
var request = FFIRequest.create()..event = UserEvent.SignIn.toString();
return protobufToBytes(payload).fold(
(payload) {
request.payload = payload;
return Dispatch.asyncRequest(request).then((response) {
try {
if (response.code != FFIStatusCode.Ok) {
return right(FlowyError.from(response));
} else {
final pb = UserSignInResult.fromBuffer(response.payload);
return left(pb);
}
} catch (e, s) {
final error =
FlowyError.fromError('${e.runtimeType}. Stack trace: $s');
return right(error);
}
});
},
(err) => Future(() {
return right(FlowyError.fromError(err));
}),
);
}
}

View File

@ -0,0 +1,88 @@
import 'dart:ffi';
import 'package:dartz/dartz.dart';
import 'package:flowy_logger/flowy_logger.dart';
import 'package:flowy_sdk/dispatch/flowy_error.dart';
import 'package:flowy_sdk/protobuf/ffi_response.pb.dart';
import 'package:isolates/isolates.dart';
import 'package:isolates/ports.dart';
import 'package:ffi/ffi.dart';
// ignore: unused_import
import 'package:flutter/services.dart';
import 'dart:async';
import 'dart:typed_data';
import 'package:flowy_sdk/ffi/ffi.dart' as ffi;
import 'package:flowy_sdk/protobuf.dart';
import 'package:protobuf/protobuf.dart';
part 'code_gen.dart';
enum FFIException {
RequestIsEmpty,
}
class DispatchException implements Exception {
FFIException type;
DispatchException(this.type);
}
class Dispatch {
static Future<FFIResponse> asyncRequest(FFIRequest request) {
try {
return _asyncRequest(request).future.then((value) {
try {
final response = FFIResponse.fromBuffer(value);
return Future.microtask(() => response);
} catch (e, s) {
Log.error('FlowyFFI asyncRequest error: ${e.runtimeType}\n');
Log.error('Stack trace \n $s');
final response = error_response(request, "${e.runtimeType}");
return Future.microtask(() => response);
}
});
} catch (e, s) {
Log.error('FlowyFFI asyncRequest error: ${e.runtimeType}\n');
Log.error('Stack trace \n $s');
final response = error_response(request, "${e.runtimeType}");
return Future.microtask(() => response);
}
}
}
Completer<Uint8List> _asyncRequest(FFIRequest request) {
Uint8List bytes = request.writeToBuffer();
assert(bytes.isEmpty == false);
if (bytes.isEmpty) {
throw DispatchException(FFIException.RequestIsEmpty);
}
final Pointer<Uint8> input = calloc.allocate<Uint8>(bytes.length);
final list = input.asTypedList(bytes.length);
list.setAll(0, bytes);
final completer = Completer<Uint8List>();
final port = singleCompletePort(completer);
ffi.async_command(port.nativePort, input, bytes.length);
calloc.free(input);
return completer;
}
FFIResponse error_response(FFIRequest request, String message) {
var response = FFIResponse();
response.code = FFIStatusCode.Err;
response.error = "${request.event}: ${message}";
return response;
}
Either<Uint8List, String> protobufToBytes<T extends GeneratedMessage>(
T? message) {
try {
if (message != null) {
return left(message.writeToBuffer());
} else {
return left(Uint8List.fromList([]));
}
} catch (e, s) {
return right('FlowyFFI error: ${e.runtimeType}. Stack trace: $s');
}
}

View File

@ -0,0 +1,35 @@
import '../protobuf/ffi_response.pb.dart';
class FlowyError {
late FFIStatusCode _statusCode;
late String _error;
FFIStatusCode get statusCode {
return _statusCode;
}
String get error {
return _error;
}
bool get has_error {
return _statusCode != FFIStatusCode.Ok;
}
String toString() {
return "$_statusCode: $_error";
}
FlowyError({required FFIStatusCode statusCode, required String error}) {
_statusCode = statusCode;
_error = error;
}
factory FlowyError.from(FFIResponse resp) {
return FlowyError(statusCode: resp.code, error: resp.error);
}
factory FlowyError.fromError(String error) {
return FlowyError(statusCode: FFIStatusCode.Err, error: error);
}
}

View File

@ -5,7 +5,6 @@ import 'package:isolates/isolates.dart';
// ignore: import_of_legacy_library_into_null_safe
import 'package:isolates/ports.dart';
import 'package:ffi/ffi.dart';
// ignore: unused_import
import 'package:flutter/services.dart';
import 'dart:async';

View File

@ -2,12 +2,16 @@ export 'package:async/async.dart';
import 'dart:io';
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/flowy_error.dart';
import 'package:flutter/services.dart';
import 'dart:ffi';
import 'ffi/adaptor.dart';
import 'ffi/ffi.dart' as ffi;
import 'package:ffi/ffi.dart';
import 'package:flowy_sdk/protobuf.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
class FlowySDK {
static const MethodChannel _channel = MethodChannel('flowy_sdk');
static Future<String> get platformVersion async {
@ -23,7 +27,20 @@ class FlowySDK {
ffi.store_dart_post_cobject(NativeApi.postCObject);
ffi.init_sdk(sdkDir.path.toNativeUtf8());
final resp = await FFIAdaptor.asyncRequest();
print(resp);
final params = UserSignInParams.create();
params.email = "nathan.fu@gmail.com";
params.password = "Helloworld!2";
Either<UserSignInResult, FlowyError> resp =
await UserEventSignIn(params).send();
resp.fold(
(result) {
print(result);
},
(error) {
print(error);
},
);
}
}

View File

@ -3,4 +3,5 @@ export 'protobuf/ffi_response.pb.dart';
export 'protobuf/ffi_request.pb.dart';
export 'protobuf/sign_up.pb.dart';
export 'protobuf/sign_in.pb.dart';
export 'protobuf/event.pb.dart';
export 'protobuf/user.pb.dart';

View File

@ -0,0 +1,11 @@
///
// Generated code. Do not modify.
// source: event.proto
//
// @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
import 'dart:core' as $core;
export 'event.pbenum.dart';

View File

@ -0,0 +1,30 @@
///
// Generated code. Do not modify.
// source: event.proto
//
// @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 UserEvent extends $pb.ProtobufEnum {
static const UserEvent AuthCheck = UserEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AuthCheck');
static const UserEvent SignIn = UserEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SignIn');
static const UserEvent SignUp = UserEvent._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SignUp');
static const UserEvent SignOut = UserEvent._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SignOut');
static const $core.List<UserEvent> values = <UserEvent> [
AuthCheck,
SignIn,
SignUp,
SignOut,
];
static final $core.Map<$core.int, UserEvent> _byValue = $pb.ProtobufEnum.initByValue(values);
static UserEvent? valueOf($core.int value) => _byValue[value];
const UserEvent._($core.int v, $core.String n) : super(v, n);
}

View File

@ -0,0 +1,18 @@
///
// Generated code. Do not modify.
// source: event.proto
//
// @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
import 'dart:core' as $core;
const UserEvent$json = const {
'1': 'UserEvent',
'2': const [
const {'1': 'AuthCheck', '2': 0},
const {'1': 'SignIn', '2': 1},
const {'1': 'SignUp', '2': 2},
const {'1': 'SignOut', '2': 3},
],
};

View File

@ -0,0 +1,9 @@
///
// Generated code. Do not modify.
// source: event.proto
//
// @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
export 'event.pb.dart';

View File

@ -9,30 +9,34 @@ import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
import 'ffi_response.pbenum.dart';
export 'ffi_response.pbenum.dart';
class FFIResponse extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FFIResponse', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'event')
..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'payload', $pb.PbFieldType.OY)
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'error')
..a<$core.List<$core.int>>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'payload', $pb.PbFieldType.OY)
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'error')
..e<FFIStatusCode>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: FFIStatusCode.Unknown, valueOf: FFIStatusCode.valueOf, enumValues: FFIStatusCode.values)
..hasRequiredFields = false
;
FFIResponse._() : super();
factory FFIResponse({
$core.String? event,
$core.List<$core.int>? payload,
$core.String? error,
FFIStatusCode? code,
}) {
final _result = create();
if (event != null) {
_result.event = event;
}
if (payload != null) {
_result.payload = payload;
}
if (error != null) {
_result.error = error;
}
if (code != null) {
_result.code = code;
}
return _result;
}
factory FFIResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@ -57,30 +61,30 @@ class FFIResponse extends $pb.GeneratedMessage {
static FFIResponse? _defaultInstance;
@$pb.TagNumber(1)
$core.String get event => $_getSZ(0);
$core.List<$core.int> get payload => $_getN(0);
@$pb.TagNumber(1)
set event($core.String v) { $_setString(0, v); }
set payload($core.List<$core.int> v) { $_setBytes(0, v); }
@$pb.TagNumber(1)
$core.bool hasEvent() => $_has(0);
$core.bool hasPayload() => $_has(0);
@$pb.TagNumber(1)
void clearEvent() => clearField(1);
void clearPayload() => clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get payload => $_getN(1);
$core.String get error => $_getSZ(1);
@$pb.TagNumber(2)
set payload($core.List<$core.int> v) { $_setBytes(1, v); }
set error($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasPayload() => $_has(1);
$core.bool hasError() => $_has(1);
@$pb.TagNumber(2)
void clearPayload() => clearField(2);
void clearError() => clearField(2);
@$pb.TagNumber(3)
$core.String get error => $_getSZ(2);
FFIStatusCode get code => $_getN(2);
@$pb.TagNumber(3)
set error($core.String v) { $_setString(2, v); }
set code(FFIStatusCode v) { setField(3, v); }
@$pb.TagNumber(3)
$core.bool hasError() => $_has(2);
$core.bool hasCode() => $_has(2);
@$pb.TagNumber(3)
void clearError() => clearField(3);
void clearCode() => clearField(3);
}

View File

@ -5,3 +5,24 @@
// @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 FFIStatusCode extends $pb.ProtobufEnum {
static const FFIStatusCode Unknown = FFIStatusCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown');
static const FFIStatusCode Ok = FFIStatusCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ok');
static const FFIStatusCode Err = FFIStatusCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Err');
static const $core.List<FFIStatusCode> values = <FFIStatusCode> [
Unknown,
Ok,
Err,
];
static final $core.Map<$core.int, FFIStatusCode> _byValue = $pb.ProtobufEnum.initByValue(values);
static FFIStatusCode? valueOf($core.int value) => _byValue[value];
const FFIStatusCode._($core.int v, $core.String n) : super(v, n);
}

View File

@ -6,12 +6,21 @@
// 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
import 'dart:core' as $core;
const FFIResponse$json = const {
'1': 'FFIResponse',
const FFIStatusCode$json = const {
'1': 'FFIStatusCode',
'2': const [
const {'1': 'event', '3': 1, '4': 1, '5': 9, '10': 'event'},
const {'1': 'payload', '3': 2, '4': 1, '5': 12, '10': 'payload'},
const {'1': 'error', '3': 3, '4': 1, '5': 9, '10': 'error'},
const {'1': 'Unknown', '2': 0},
const {'1': 'Ok', '2': 1},
const {'1': 'Err', '2': 2},
],
};
const FFIResponse$json = const {
'1': 'FFIResponse',
'2': const [
const {'1': 'payload', '3': 1, '4': 1, '5': 12, '10': 'payload'},
const {'1': 'error', '3': 2, '4': 1, '5': 9, '10': 'error'},
const {'1': 'code', '3': 3, '4': 1, '5': 14, '6': '.FFIStatusCode', '10': 'code'},
],
};

View File

@ -209,6 +209,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
flutter_test:
dependency: "direct dev"
description: flutter
@ -284,6 +291,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
logger:
dependency: transitive
description:

View File

@ -259,7 +259,7 @@ packages:
source: hosted
version: "7.0.1"
flutter_lints:
dependency: "direct main"
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"

View File

@ -1,10 +1,11 @@
mod c;
mod model;
mod protobuf;
mod util;
use crate::{
c::{extend_front_four_bytes_into_bytes, forget_rust},
protobuf::FFIRequest,
model::{FFIRequest, FFIResponse},
};
use flowy_sdk::*;
use flowy_sys::prelude::*;
@ -30,7 +31,7 @@ pub extern "C" fn init_sdk(path: *mut c_char) -> i64 {
#[no_mangle]
pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
let mut request: DispatchRequest = FFIRequest::from_u8_pointer(input, len).into();
let request: DispatchRequest = FFIRequest::from_u8_pointer(input, len).into();
log::trace!(
"[FFI]: {} Async Event: {:?} with {} port",
&request.id,
@ -38,16 +39,10 @@ pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
port
);
request = request.callback(Box::new(move |resp: EventResponse| {
let bytes = match resp.payload {
Payload::Bytes(bytes) => bytes,
Payload::None => vec![],
};
let _ = EventDispatch::async_send(request, move |resp: EventResponse| {
log::trace!("[FFI]: Post data to dart through {} port", port);
Box::pin(spawn_future(async { bytes }, port))
}));
let _ = EventDispatch::async_send(request);
Box::pin(post_to_flutter(resp, port))
});
}
#[no_mangle]
@ -66,13 +61,17 @@ pub extern "C" fn sync_command(input: *const u8, len: usize) -> *const u8 {
#[no_mangle]
pub extern "C" fn link_me_please() {}
use flowy_sys::prelude::ToBytes;
#[inline(always)]
async fn spawn_future<F>(future: F, port: i64)
where
F: Future<Output = Vec<u8>> + Send + 'static,
{
async fn post_to_flutter(response: EventResponse, port: i64) {
let isolate = allo_isolate::Isolate::new(port);
match isolate.catch_unwind(future).await {
match isolate
.catch_unwind(async {
let ffi_resp = FFIResponse::from(response);
ffi_resp.into_bytes().unwrap()
})
.await
{
Ok(_success) => {
log::trace!("[FFI]: Post data to dart success");
},
@ -85,15 +84,3 @@ where
},
}
}
impl std::convert::From<FFIRequest> for DispatchRequest {
fn from(ffi_request: FFIRequest) -> Self {
let payload = if !ffi_request.payload.is_empty() {
Payload::Bytes(ffi_request.payload)
} else {
Payload::None
};
let request = DispatchRequest::new(ffi_request.event).payload(payload);
request
}
}

View File

@ -1,13 +1,14 @@
use flowy_derive::ProtoBuf;
use flowy_sys::prelude::DispatchRequest;
use std::convert::TryFrom;
#[derive(Default, ProtoBuf)]
pub struct FFIRequest {
#[pb(index = 1)]
event: String,
pub(crate) event: String,
#[pb(index = 2)]
payload: Vec<u8>,
pub(crate) payload: Vec<u8>,
}
impl FFIRequest {
@ -17,3 +18,7 @@ impl FFIRequest {
request
}
}
impl std::convert::Into<DispatchRequest> for FFIRequest {
fn into(self) -> DispatchRequest { DispatchRequest::new(self.event).payload(self.payload) }
}

View File

@ -1,13 +1,50 @@
use flowy_derive::ProtoBuf;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_sys::prelude::{EventResponse, Payload, StatusCode};
#[derive(ProtoBuf_Enum, Clone, Copy)]
pub enum FFIStatusCode {
Unknown = 0,
Ok = 1,
Err = 2,
}
impl std::default::Default for FFIStatusCode {
fn default() -> FFIStatusCode { FFIStatusCode::Unknown }
}
#[derive(ProtoBuf, Default)]
pub struct FFIResponse {
#[pb(index = 1)]
event: String,
#[pb(index = 2)]
payload: Vec<u8>,
#[pb(index = 3)]
#[pb(index = 2)]
error: String,
#[pb(index = 3)]
code: FFIStatusCode,
}
impl std::convert::From<EventResponse> for FFIResponse {
fn from(resp: EventResponse) -> Self {
let payload = match resp.payload {
Payload::Bytes(bytes) => bytes,
Payload::None => vec![],
};
let error = match resp.error {
Some(e) => format!("{}", e),
None => "".to_owned(),
};
let code = match resp.status_code {
StatusCode::Ok => FFIStatusCode::Ok,
StatusCode::Err => FFIStatusCode::Err,
};
FFIResponse {
payload,
error,
code,
}
}
}

View File

@ -26,9 +26,9 @@
#[derive(PartialEq,Clone,Default)]
pub struct FFIResponse {
// message fields
pub event: ::std::string::String,
pub payload: ::std::vec::Vec<u8>,
pub error: ::std::string::String,
pub code: FFIStatusCode,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
@ -45,33 +45,7 @@ impl FFIResponse {
::std::default::Default::default()
}
// string event = 1;
pub fn get_event(&self) -> &str {
&self.event
}
pub fn clear_event(&mut self) {
self.event.clear();
}
// Param is passed by value, moved
pub fn set_event(&mut self, v: ::std::string::String) {
self.event = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_event(&mut self) -> &mut ::std::string::String {
&mut self.event
}
// Take field
pub fn take_event(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.event, ::std::string::String::new())
}
// bytes payload = 2;
// bytes payload = 1;
pub fn get_payload(&self) -> &[u8] {
@ -97,7 +71,7 @@ impl FFIResponse {
::std::mem::replace(&mut self.payload, ::std::vec::Vec::new())
}
// string error = 3;
// string error = 2;
pub fn get_error(&self) -> &str {
@ -122,6 +96,21 @@ impl FFIResponse {
pub fn take_error(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.error, ::std::string::String::new())
}
// .FFIStatusCode code = 3;
pub fn get_code(&self) -> FFIStatusCode {
self.code
}
pub fn clear_code(&mut self) {
self.code = FFIStatusCode::Unknown;
}
// Param is passed by value, moved
pub fn set_code(&mut self, v: FFIStatusCode) {
self.code = v;
}
}
impl ::protobuf::Message for FFIResponse {
@ -134,14 +123,14 @@ impl ::protobuf::Message for FFIResponse {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.event)?;
},
2 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.payload)?;
},
3 => {
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.error)?;
},
3 => {
::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.code, 3, &mut self.unknown_fields)?
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
@ -154,14 +143,14 @@ impl ::protobuf::Message for FFIResponse {
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.event.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.event);
}
if !self.payload.is_empty() {
my_size += ::protobuf::rt::bytes_size(2, &self.payload);
my_size += ::protobuf::rt::bytes_size(1, &self.payload);
}
if !self.error.is_empty() {
my_size += ::protobuf::rt::string_size(3, &self.error);
my_size += ::protobuf::rt::string_size(2, &self.error);
}
if self.code != FFIStatusCode::Unknown {
my_size += ::protobuf::rt::enum_size(3, self.code);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
@ -169,14 +158,14 @@ impl ::protobuf::Message for FFIResponse {
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.event.is_empty() {
os.write_string(1, &self.event)?;
}
if !self.payload.is_empty() {
os.write_bytes(2, &self.payload)?;
os.write_bytes(1, &self.payload)?;
}
if !self.error.is_empty() {
os.write_string(3, &self.error)?;
os.write_string(2, &self.error)?;
}
if self.code != FFIStatusCode::Unknown {
os.write_enum(3, ::protobuf::ProtobufEnum::value(&self.code))?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
@ -216,11 +205,6 @@ impl ::protobuf::Message for FFIResponse {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"event",
|m: &FFIResponse| { &m.event },
|m: &mut FFIResponse| { &mut m.event },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
"payload",
|m: &FFIResponse| { &m.payload },
@ -231,6 +215,11 @@ impl ::protobuf::Message for FFIResponse {
|m: &FFIResponse| { &m.error },
|m: &mut FFIResponse| { &mut m.error },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<FFIStatusCode>>(
"code",
|m: &FFIResponse| { &m.code },
|m: &mut FFIResponse| { &mut m.code },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<FFIResponse>(
"FFIResponse",
fields,
@ -247,9 +236,9 @@ impl ::protobuf::Message for FFIResponse {
impl ::protobuf::Clear for FFIResponse {
fn clear(&mut self) {
self.event.clear();
self.payload.clear();
self.error.clear();
self.code = FFIStatusCode::Unknown;
self.unknown_fields.clear();
}
}
@ -266,20 +255,82 @@ impl ::protobuf::reflect::ProtobufValue for FFIResponse {
}
}
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum FFIStatusCode {
Unknown = 0,
Ok = 1,
Err = 2,
}
impl ::protobuf::ProtobufEnum for FFIStatusCode {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<FFIStatusCode> {
match value {
0 => ::std::option::Option::Some(FFIStatusCode::Unknown),
1 => ::std::option::Option::Some(FFIStatusCode::Ok),
2 => ::std::option::Option::Some(FFIStatusCode::Err),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [FFIStatusCode] = &[
FFIStatusCode::Unknown,
FFIStatusCode::Ok,
FFIStatusCode::Err,
];
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::<FFIStatusCode>("FFIStatusCode", file_descriptor_proto())
})
}
}
impl ::std::marker::Copy for FFIStatusCode {
}
impl ::std::default::Default for FFIStatusCode {
fn default() -> Self {
FFIStatusCode::Unknown
}
}
impl ::protobuf::reflect::ProtobufValue for FFIStatusCode {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x12ffi_response.proto\"S\n\x0bFFIResponse\x12\x14\n\x05event\x18\x01\
\x20\x01(\tR\x05event\x12\x18\n\x07payload\x18\x02\x20\x01(\x0cR\x07payl\
oad\x12\x14\n\x05error\x18\x03\x20\x01(\tR\x05errorJ\xcf\x01\n\x06\x12\
\x04\0\0\x06\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\
\x02\0\x06\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x13\n\x0b\n\x04\x04\0\
\x02\0\x12\x03\x03\x04\x15\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\x10\n\x0c\n\x05\x04\0\x02\0\
\x03\x12\x03\x03\x13\x14\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x16\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\x11\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x14\x15\
\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x15\n\x0c\n\x05\x04\0\x02\x02\
\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x0b\x10\
\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x13\x14b\x06proto3\
\n\x12ffi_response.proto\"a\n\x0bFFIResponse\x12\x18\n\x07payload\x18\
\x01\x20\x01(\x0cR\x07payload\x12\x14\n\x05error\x18\x02\x20\x01(\tR\x05\
error\x12\"\n\x04code\x18\x03\x20\x01(\x0e2\x0e.FFIStatusCodeR\x04code*-\
\n\rFFIStatusCode\x12\x0b\n\x07Unknown\x10\0\x12\x06\n\x02Ok\x10\x01\x12\
\x07\n\x03Err\x10\x02J\xe2\x02\n\x06\x12\x04\0\0\x0b\x01\n\x08\n\x01\x0c\
\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x06\x01\n\n\n\x03\x04\0\
\x01\x12\x03\x02\x08\x13\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x16\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\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\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\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\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\x1b\n\x0c\n\x05\x04\0\x02\x02\x06\x12\x03\x05\x04\
\x11\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x12\x16\n\x0c\n\x05\x04\0\
\x02\x02\x03\x12\x03\x05\x19\x1a\n\n\n\x02\x05\0\x12\x04\x07\0\x0b\x01\n\
\n\n\x03\x05\0\x01\x12\x03\x07\x05\x12\n\x0b\n\x04\x05\0\x02\0\x12\x03\
\x08\x04\x10\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x08\x04\x0b\n\x0c\n\x05\
\x05\0\x02\0\x02\x12\x03\x08\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\t\
\x04\x0b\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\t\x04\x06\n\x0c\n\x05\x05\
\0\x02\x01\x02\x12\x03\t\t\n\n\x0b\n\x04\x05\0\x02\x02\x12\x03\n\x04\x0c\
\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\n\x04\x07\n\x0c\n\x05\x05\0\x02\
\x02\x02\x12\x03\n\n\x0bb\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -1,7 +1,12 @@
syntax = "proto3";
message FFIResponse {
string event = 1;
bytes payload = 2;
string error = 3;
bytes payload = 1;
string error = 2;
FFIStatusCode code = 3;
}
enum FFIStatusCode {
Unknown = 0;
Ok = 1;
Err = 2;
}

View File

@ -0,0 +1 @@

View File

@ -25,6 +25,9 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
| "UserSignInRequest"
| "UserSignInResult"
=> TypeCategory::Protobuf,
"FFIStatusCode"
| "UserEvent"
=> TypeCategory::Enum,
"Option" => TypeCategory::Opt,
_ => TypeCategory::Primitive,

View File

@ -60,7 +60,7 @@ fn token_stream_for_one_of(ctxt: &Ctxt, field: &ASTField) -> Option<TokenStream>
let ty = ty_info.ty;
Some(quote! {
if pb.#has_func() {
let enum_de_from_pb = #ty::try_from(&mut pb.#get_func()).unwrap();
let enum_de_from_pb = #ty::try_from(&pb.#get_func()).unwrap();
o.#member = Some(enum_de_from_pb);
}
})
@ -122,7 +122,7 @@ fn token_stream_for_field(
TypeCategory::Enum => {
let ty = ty_info.ty;
Some(quote! {
let enum_de_from_pb = #ty::try_from(&mut pb.#member).unwrap();
let enum_de_from_pb = #ty::try_from(&pb.#member).unwrap();
o.#member = enum_de_from_pb;
})

View File

@ -5,27 +5,36 @@ use proc_macro2::TokenStream;
pub fn make_enum_token_stream(_ctxt: &Ctxt, cont: &ASTContainer) -> Option<TokenStream> {
let enum_ident = &cont.ident;
let pb_enum = cont.attrs.pb_enum_type()?;
let _build_to_pb_enum = cont.data.all_idents().map(|i| {
let build_to_pb_enum = cont.data.all_idents().map(|i| {
let token_stream: TokenStream = quote! {
#enum_ident::#i => #pb_enum::#i,
#enum_ident::#i => crate::protobuf::#pb_enum::#i,
};
token_stream
});
let build_from_pb_enum = cont.data.all_idents().map(|i| {
let token_stream: TokenStream = quote! {
#pb_enum::#i => #enum_ident::#i,
crate::protobuf::#pb_enum::#i => #enum_ident::#i,
};
token_stream
});
Some(quote! {
impl std::convert::TryFrom<#pb_enum> for #enum_ident {
impl std::convert::TryFrom<&crate::protobuf::#pb_enum> for #enum_ident {
type Error = String;
fn try_from(pb: #pb_enum) -> Result<Self, Self::Error> {
match field_type {
fn try_from(pb:&crate::protobuf::#pb_enum) -> Result<Self, Self::Error> {
Ok(match pb {
#(#build_from_pb_enum)*
}
})
}
}
impl std::convert::TryInto<crate::protobuf::#pb_enum> for #enum_ident {
type Error = String;
fn try_into(self) -> Result<crate::protobuf::#pb_enum, Self::Error> {
Ok(match self {
#(#build_to_pb_enum)*
})
}
}
})

View File

@ -58,7 +58,7 @@ fn se_token_stream_for_field(ctxt: &Ctxt, field: &ASTField, _take: bool) -> Opti
let set_func = format_ident!("set_{}", ident.to_string());
Some(quote! {
match self.#member {
Some(ref s) => { pb.#set_func(s.to_protobuf()) }
Some(ref s) => { pb.#set_func(s.try_into().unwrap()) }
None => {}
}
})
@ -98,7 +98,7 @@ fn gen_token_stream(
}
},
TypeCategory::Protobuf => Some(
quote! { pb.#member = ::protobuf::SingularPtrField::some(self.#member.to_protobuf()); },
quote! { pb.#member = ::protobuf::SingularPtrField::some(self.#member.try_into().unwrap()); },
),
TypeCategory::Opt => {
gen_token_stream(ctxt, member, ty_info.bracket_ty_info.unwrap().ty, true)
@ -109,7 +109,7 @@ fn gen_token_stream(
// flowy_protobuf::#pb_enum_ident::from_i32(self.#member.value()).unwrap();
// })
Some(quote! {
pb.#member = self.#member.to_protobuf();
pb.#member = self.#member.try_into().unwrap();
})
},
_ => Some(quote! { pb.#member = self.#member; }),
@ -124,7 +124,7 @@ fn token_stream_for_vec(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Op
pb.#member = ::protobuf::RepeatedField::from_vec(
self.#member
.iter()
.map(|m| m.to_protobuf())
.map(|m| m.try_into().unwrap())
.collect());
}),
TypeCategory::Bytes => Some(quote! { pb.#member = self.#member.clone(); }),
@ -146,7 +146,7 @@ fn token_stream_for_map(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Op
Some(quote! {
let mut m: std::collections::HashMap<String, #flowy_protobuf::#value_type> = std::collections::HashMap::new();
self.#member.iter().for_each(|(k,v)| {
m.insert(k.clone(), v.to_protobuf());
m.insert(k.clone(), v.try_into().unwrap());
});
pb.#member = m;
})

View File

@ -15,8 +15,4 @@ impl FlowySDK {
}
}
pub async fn async_send(request: DispatchRequest) -> EventResponse {
EventDispatch::async_send(request).await
}
pub fn sync_send(request: DispatchRequest) -> EventResponse { EventDispatch::sync_send(request) }

View File

@ -46,7 +46,14 @@ impl EventDispatch {
*(EVENT_DISPATCH.write().unwrap()) = Some(dispatch);
}
pub fn async_send(request: DispatchRequest) -> DispatchFuture {
pub fn async_send<Req, Callback>(request: Req, callback: Callback) -> DispatchFuture
where
Req: std::convert::Into<DispatchRequest>,
Callback: FnOnce(EventResponse) -> BoxFuture<'static, ()> + 'static + Send + Sync,
{
let mut request = request.into();
request.callback = Some(Box::new(callback));
match EVENT_DISPATCH.read() {
Ok(dispatch) => {
let dispatch = dispatch.as_ref().unwrap();
@ -81,7 +88,13 @@ impl EventDispatch {
}
pub fn sync_send(request: DispatchRequest) -> EventResponse {
futures::executor::block_on(async { EventDispatch::async_send(request).await })
futures::executor::block_on(async {
EventDispatch::async_send(request, |response| {
dbg!(&response);
Box::pin(async {})
})
.await
})
}
}
@ -130,16 +143,9 @@ impl DispatchRequest {
pub fn payload<P>(mut self, payload: P) -> Self
where
P: TryInto<Payload, Error = String>,
P: Into<Payload>,
{
let payload = match payload.try_into() {
Ok(payload) => payload,
Err(e) => {
log::error!("{}", e);
Payload::None
},
};
self.payload = payload;
self.payload = payload.into();
self
}

View File

@ -10,10 +10,6 @@ pub fn setup_env() {
});
}
pub async fn async_send(request: DispatchRequest) -> EventResponse {
EventDispatch::async_send(request).await
}
pub fn init_dispatch<F>(module_factory: F)
where
F: FnOnce() -> Vec<Module>,

View File

@ -10,6 +10,13 @@ async fn test_init() {
init_dispatch(|| vec![Module::new().event(event, hello)]);
let request = DispatchRequest::new(event);
let resp = async_send(request).await;
dbg!(&resp);
let _ = EventDispatch::async_send(
request,
Some(|resp| {
Box::pin(async move {
dbg!(&resp);
})
}),
)
.await;
}

View File

@ -66,7 +66,8 @@ impl EventTester {
P: ToBytes,
{
let mut request = self.request.take().unwrap();
request = request.payload(Data(payload));
let bytes = payload.into_bytes().unwrap();
request = request.payload(bytes);
self.request = Some(request);
self
}
@ -78,7 +79,9 @@ impl EventTester {
#[allow(dead_code)]
pub async fn async_send(mut self) -> Self {
let resp = async_send(self.request.take().unwrap()).await;
let resp =
EventDispatch::async_send(self.request.take().unwrap(), |_| Box::pin(async {})).await;
if let Some(ref status_code) = self.assert_status_code {
assert_eq!(&resp.status_code, status_code)
}

View File

@ -0,0 +1,27 @@
use derive_more::Display;
use flowy_derive::ProtoBuf_Enum;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum)]
pub enum UserEvent {
#[display(fmt = "AuthCheck")]
AuthCheck = 0,
#[display(fmt = "SignIn")]
SignIn = 1,
#[display(fmt = "SignUp")]
SignUp = 2,
#[display(fmt = "SignOut")]
SignOut = 3,
}
// impl std::convert::TryFrom<&crate::protobuf::UserEvent> for UserEvent {
// type Error = String;
// fn try_from(pb: &crate::protobuf::UserEvent) -> Result<Self, Self::Error>
// { let a = UserEvent::SignIn;
// match pb {
// crate::protobuf::UserEvent::AuthCheck => { UserEvent::SignIn }
// UserEvent::SignIn => { UserEvent::SignIn }
// UserEvent::SignUp => {UserEvent::SignIn }
// UserEvent::SignOut => {UserEvent::SignIn}
// }
// }
// }

View File

@ -1,3 +1,4 @@
pub mod event;
pub mod user;
pub use user::*;

View File

@ -5,5 +5,5 @@ pub mod module;
mod protobuf;
pub mod prelude {
pub use crate::{domain::*, handlers::auth::*, module::UserEvent::*};
pub use crate::{domain::*, handlers::auth::*};
}

View File

@ -1,20 +1,6 @@
use crate::handlers::*;
use crate::{domain::event::UserEvent, handlers::*};
use flowy_sys::prelude::*;
use derive_more::Display;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash)]
pub enum UserEvent {
#[display(fmt = "AuthCheck")]
AuthCheck = 0,
#[display(fmt = "SignIn")]
SignIn = 1,
#[display(fmt = "SignUp")]
SignUp = 2,
#[display(fmt = "SignOut")]
SignOut = 3,
}
pub fn create() -> Module {
Module::new()
.name("Flowy-User")

View File

@ -0,0 +1,108 @@
// This file is generated by rust-protobuf 2.22.1. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy::all)]
#![allow(unused_attributes)]
#![cfg_attr(rustfmt, rustfmt::skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unused_imports)]
#![allow(unused_results)]
//! Generated file from `event.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum UserEvent {
AuthCheck = 0,
SignIn = 1,
SignUp = 2,
SignOut = 3,
}
impl ::protobuf::ProtobufEnum for UserEvent {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<UserEvent> {
match value {
0 => ::std::option::Option::Some(UserEvent::AuthCheck),
1 => ::std::option::Option::Some(UserEvent::SignIn),
2 => ::std::option::Option::Some(UserEvent::SignUp),
3 => ::std::option::Option::Some(UserEvent::SignOut),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [UserEvent] = &[
UserEvent::AuthCheck,
UserEvent::SignIn,
UserEvent::SignUp,
UserEvent::SignOut,
];
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::<UserEvent>("UserEvent", file_descriptor_proto())
})
}
}
impl ::std::marker::Copy for UserEvent {
}
impl ::std::default::Default for UserEvent {
fn default() -> Self {
UserEvent::AuthCheck
}
}
impl ::protobuf::reflect::ProtobufValue for UserEvent {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0bevent.proto*?\n\tUserEvent\x12\r\n\tAuthCheck\x10\0\x12\n\n\x06Sig\
nIn\x10\x01\x12\n\n\x06SignUp\x10\x02\x12\x0b\n\x07SignOut\x10\x03J\xce\
\x01\n\x06\x12\x04\0\0\x07\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\
\x05\0\x12\x04\x02\0\x07\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x0e\n\
\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x12\n\x0c\n\x05\x05\0\x02\0\x01\
\x12\x03\x03\x04\r\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x10\x11\n\x0b\
\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x0f\n\x0c\n\x05\x05\0\x02\x01\x01\
\x12\x03\x04\x04\n\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\r\x0e\n\x0b\
\n\x04\x05\0\x02\x02\x12\x03\x05\x04\x0f\n\x0c\n\x05\x05\0\x02\x02\x01\
\x12\x03\x05\x04\n\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x05\r\x0e\n\x0b\
\n\x04\x05\0\x02\x03\x12\x03\x06\x04\x10\n\x0c\n\x05\x05\0\x02\x03\x01\
\x12\x03\x06\x04\x0b\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x06\x0e\x0fb\
\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}

View File

@ -6,5 +6,8 @@ pub use sign_up::*;
mod sign_in;
pub use sign_in::*;
mod event;
pub use event::*;
mod user;
pub use user::*;

View File

@ -0,0 +1,8 @@
syntax = "proto3";
enum UserEvent {
AuthCheck = 0;
SignIn = 1;
SignUp = 2;
SignOut = 3;
}

View File

@ -1,5 +1,5 @@
use flowy_test::prelude::*;
use flowy_user::prelude::*;
use flowy_user::prelude::{event::UserEvent::*, *};
#[test]
fn sign_in_with_invalid_email() {

View File

@ -4,6 +4,11 @@ pub struct EventTemplate {
tera_context: Context,
}
pub const DART_IMPORTED: &'static str = r#"
/// Auto gen code from rust ast, do not edit
part of 'cqrs.dart';
"#;
pub struct EventRenderContext {
pub input_deserializer: String,
pub output_deserializer: String,
@ -21,5 +26,67 @@ impl EventTemplate {
pub fn render(&mut self, _render_context: EventRenderContext, _index: usize) -> Option<String> {
None
// if index == 0 {
// self.tera_context
// .insert("imported_dart_files", DART_IMPORTED)
// }
// self.tera_context.insert("index", &index);
//
//
//
// self.tera_context.insert(
// "command_request_struct_ident",
// &render_context.command_request_struct_ident,
// );
//
// self.tera_context
// .insert("request_deserializer", &render_context.request_deserializer);
//
// if render_context.request_deserializer.is_empty() {
// self.tera_context.insert("has_request_deserializer", &false);
// } else {
// self.tera_context.insert("has_request_deserializer", &true);
// }
// self.tera_context
// .insert("command_ident", &render_context.event);
//
// if render_context.response_deserializer.is_empty() {
// self.tera_context
// .insert("has_response_deserializer", &false);
// self.tera_context
// .insert("response_deserializer", "ResponsePacket");
// } else {
// self.tera_context.insert("has_response_deserializer", &true);
// self.tera_context.insert(
// "response_deserializer",
// &render_context.response_deserializer,
// );
// }
//
// self.tera_context
// .insert("async_cqrs_type", &render_context.async_cqrs_type);
// let repo_absolute_path =
// std::fs::canonicalize("./flowy-scripts/rust-tool/src/flutter/cqrs")
// .unwrap()
// .as_path()
// .display()
// .to_string();
//
// let template_path = format!("{}/**/*.tera", repo_absolute_path);
// let tera = match Tera::new(&template_path) {
// Ok(t) => t,
// Err(e) => {
// log::error!("Parsing error(s): {}", e);
// ::std::process::exit(1);
// }
// };
//
// match tera.render("command_request_template.tera", &self.tera_context) {
// Ok(r) => Some(r),
// Err(e) => {
// log::error!("{:?}", e);
// None
// }
// }
}
}

View File

@ -0,0 +1,72 @@
{%- if index == 0 %}
{{ imported_dart_files }}
{%- endif -%}
class {{ command_request_struct_ident }} {
{%- if has_request_deserializer %}
{{ request_deserializer }} body;
{%- else %}
Uint8List? body;
{%- endif %}
{%- if has_request_deserializer %}
{{ command_request_struct_ident }}(this.body);
{%- else %}
{{ command_request_struct_ident }}();
{%- endif %}
Future<Either<{{ response_deserializer }}, FlowyError>> send() {
final command = Command.{{ command_ident }};
var request = RequestPacket.create()
..command = command
..id = uuid();
{%- if has_request_deserializer %}
return protobufToBytes(body).fold(
(req_bytes) {
request.body = req_bytes;
return {{ async_cqrs_type }}(request).then((response) {
{%- if has_response_deserializer %}
try {
if (response.hasErr()) {
return right(FlowyError.from(response));
} else {
final pb = {{ response_deserializer }}.fromBuffer(response.body);
return left(pb);
}
} catch (e, s) {
final error = FlowyError.fromError('error: ${e.runtimeType}. Stack trace: $s', StatusCode.ProtobufDeserializeError);
return right(error);
}
{%- else %}
return left(response);
{%- endif %}
});
},
(err) => Future(() {
final error = FlowyError.fromError(err, StatusCode.ProtobufSerializeError);
return right(error);
}),
);
{%- else %}
return {{ async_cqrs_type }}(request).then((response) {
{%- if has_response_deserializer %}
try {
if (response.hasErr()) {
return right(FlowyError.from(response));
} else {
final pb = {{ response_deserializer }}.fromBuffer(response.body);
return left(pb);
}
} catch (e, s) {
final error = FlowyError.fromError('error: ${e.runtimeType}. Stack trace: $s', StatusCode.ProtobufDeserializeError);
return right(error);
}
{%- else %}
return left(response);
{%- endif %}
});
{%- endif %}
}
}

View File

@ -24,7 +24,7 @@ pub fn parse_crate_config_from(entry: &walkdir::DirEntry) -> Option<CrateConfig>
let folder_name = path.file_stem().unwrap().to_str().unwrap().to_string();
let config_path = format!("{}/Flowy.toml", crate_path);
if std::path::Path::new(&config_path).exists() {
if !std::path::Path::new(&config_path).exists() {
return None;
}