mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
generate the dart side code from the rust side event
This commit is contained in:
parent
2cb26d9e90
commit
debc8960e0
@ -1,33 +1,46 @@
|
||||
/// Auto gen code from rust ast, do not edit
|
||||
part of 'dispatch.dart';
|
||||
|
||||
class UserEventSignIn {
|
||||
UserSignInParams payload;
|
||||
class UserEventAuthCheck {
|
||||
UserSignInParams params;
|
||||
UserEventAuthCheck(this.params);
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
return paramsToBytes(params).fold(
|
||||
(bytes) {
|
||||
final request = FFIRequest.create()
|
||||
..event = UserEvent.AuthCheck.toString()
|
||||
..payload = bytes;
|
||||
|
||||
return Dispatch.asyncRequest(request)
|
||||
.then((bytesResult) => bytesResult.fold(
|
||||
(bytes) => left(UserSignInResult.fromBuffer(bytes)),
|
||||
(error) => right(error),
|
||||
));
|
||||
},
|
||||
(err) => Future(() {
|
||||
return right(FlowyError.fromError(err));
|
||||
}),
|
||||
(err) => Future(() => right(err)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UserEventSignIn {
|
||||
UserSignInParams params;
|
||||
UserEventSignIn(this.params);
|
||||
|
||||
Future<Either<UserSignInResult, FlowyError>> send() {
|
||||
return paramsToBytes(params).fold(
|
||||
(bytes) {
|
||||
final request = FFIRequest.create()
|
||||
..event = UserEvent.SignIn.toString()
|
||||
..payload = bytes;
|
||||
|
||||
return Dispatch.asyncRequest(request)
|
||||
.then((bytesResult) => bytesResult.fold(
|
||||
(bytes) => left(UserSignInResult.fromBuffer(bytes)),
|
||||
(error) => right(error),
|
||||
));
|
||||
},
|
||||
(err) => Future(() => right(err)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -26,29 +26,48 @@ class DispatchException implements Exception {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
static Future<Either<Uint8List, FlowyError>> asyncRequest(
|
||||
FFIRequest request) {
|
||||
// FFIRequest => Rust SDK
|
||||
final bytesFuture = _sendToRust(request);
|
||||
|
||||
// Rust SDK => FFIResponse
|
||||
final responseFuture = _extractResponse(bytesFuture);
|
||||
|
||||
// FFIResponse's payload is the bytes of the Response object
|
||||
final payloadFuture = _extractPayload(responseFuture);
|
||||
|
||||
return payloadFuture;
|
||||
}
|
||||
}
|
||||
|
||||
Completer<Uint8List> _asyncRequest(FFIRequest request) {
|
||||
Future<Either<Uint8List, FlowyError>> _extractPayload(
|
||||
Future<Either<FFIResponse, FlowyError>> responseFuture) {
|
||||
return responseFuture.then((response) {
|
||||
return response.fold(
|
||||
(l) => left(Uint8List.fromList(l.payload)),
|
||||
(r) => right(r),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<Either<FFIResponse, FlowyError>> _extractResponse(
|
||||
Completer<Uint8List> bytesFuture) {
|
||||
return bytesFuture.future.then((bytes) {
|
||||
try {
|
||||
final response = FFIResponse.fromBuffer(bytes);
|
||||
if (response.code != FFIStatusCode.Ok) {
|
||||
return right(FlowyError.from(response));
|
||||
}
|
||||
|
||||
return left(response);
|
||||
} catch (e, s) {
|
||||
return right(StackTraceError(e, s).toFlowyError());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Completer<Uint8List> _sendToRust(FFIRequest request) {
|
||||
Uint8List bytes = request.writeToBuffer();
|
||||
assert(bytes.isEmpty == false);
|
||||
if (bytes.isEmpty) {
|
||||
@ -67,14 +86,7 @@ Completer<Uint8List> _asyncRequest(FFIRequest request) {
|
||||
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>(
|
||||
Either<Uint8List, FlowyError> paramsToBytes<T extends GeneratedMessage>(
|
||||
T? message) {
|
||||
try {
|
||||
if (message != null) {
|
||||
@ -83,6 +95,32 @@ Either<Uint8List, String> protobufToBytes<T extends GeneratedMessage>(
|
||||
return left(Uint8List.fromList([]));
|
||||
}
|
||||
} catch (e, s) {
|
||||
return right('FlowyFFI error: ${e.runtimeType}. Stack trace: $s');
|
||||
return right(FlowyError.fromError('${e.runtimeType}. Stack trace: $s'));
|
||||
}
|
||||
}
|
||||
|
||||
class StackTraceError {
|
||||
Object error;
|
||||
StackTrace trace;
|
||||
StackTraceError(
|
||||
this.error,
|
||||
this.trace,
|
||||
);
|
||||
|
||||
FlowyError toFlowyError() {
|
||||
Log.error('${error.runtimeType}\n');
|
||||
Log.error('Stack trace \n $trace');
|
||||
return FlowyError.fromError('${error.runtimeType}. Stack trace: $trace');
|
||||
}
|
||||
|
||||
String toString() {
|
||||
return '${error.runtimeType}. Stack trace: $trace';
|
||||
}
|
||||
}
|
||||
|
||||
FFIResponse error_response(FFIRequest request, StackTraceError error) {
|
||||
var response = FFIResponse();
|
||||
response.code = FFIStatusCode.Err;
|
||||
response.error = error.toString();
|
||||
return response;
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
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';
|
||||
import 'dart:typed_data';
|
||||
import 'package:flowy_sdk/ffi/ffi.dart' as ffi;
|
||||
|
||||
enum FFIExceptionType {
|
||||
RequestPacketIsEmpty,
|
||||
InvalidResponseLength,
|
||||
ResponsePacketIsInvalid,
|
||||
}
|
||||
|
||||
class FFIAdaptorException implements Exception {
|
||||
FFIExceptionType type;
|
||||
FFIAdaptorException(this.type);
|
||||
}
|
||||
|
||||
class FFICommand {
|
||||
final String event;
|
||||
final Uint8List payload;
|
||||
FFICommand(this.event, this.payload);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'event': event,
|
||||
'payload': payload,
|
||||
};
|
||||
}
|
||||
|
||||
class FFIAdaptor {
|
||||
static Completer<Uint8List> asyncRequest() {
|
||||
// final command = FFICommand(
|
||||
// "AuthCheck", Uint8List.fromList(utf8.encode("this is payload")));
|
||||
|
||||
final command = FFICommand("AuthCheck", Uint8List(0));
|
||||
|
||||
Uint8List bytes = Uint8List.fromList(utf8.encode(jsonEncode(command)));
|
||||
|
||||
assert(bytes.isEmpty == false);
|
||||
if (bytes.isEmpty) {
|
||||
throw FFIAdaptorException(FFIExceptionType.RequestPacketIsEmpty);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ use crate::{
|
||||
use flowy_sdk::*;
|
||||
use flowy_sys::prelude::*;
|
||||
use lazy_static::lazy_static;
|
||||
use std::{ffi::CStr, future::Future, os::raw::c_char};
|
||||
use std::{ffi::CStr, os::raw::c_char};
|
||||
|
||||
lazy_static! {
|
||||
pub static ref FFI_RUNTIME: tokio::runtime::Runtime =
|
||||
@ -31,11 +31,11 @@ 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 request: DispatchRequest = FFIRequest::from_u8_pointer(input, len).into();
|
||||
let request: ModuleRequest = FFIRequest::from_u8_pointer(input, len).into();
|
||||
log::trace!(
|
||||
"[FFI]: {} Async Event: {:?} with {} port",
|
||||
&request.id,
|
||||
&request.event,
|
||||
&request.id(),
|
||||
&request.event(),
|
||||
port
|
||||
);
|
||||
|
||||
@ -47,8 +47,12 @@ pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sync_command(input: *const u8, len: usize) -> *const u8 {
|
||||
let request: DispatchRequest = FFIRequest::from_u8_pointer(input, len).into();
|
||||
log::trace!("[FFI]: {} Sync Event: {:?}", &request.id, &request.event,);
|
||||
let request: ModuleRequest = FFIRequest::from_u8_pointer(input, len).into();
|
||||
log::trace!(
|
||||
"[FFI]: {} Sync Event: {:?}",
|
||||
&request.id(),
|
||||
&request.event(),
|
||||
);
|
||||
let _response = EventDispatch::sync_send(request);
|
||||
|
||||
// FFIResponse { }
|
||||
|
@ -1,5 +1,5 @@
|
||||
use flowy_derive::ProtoBuf;
|
||||
use flowy_sys::prelude::DispatchRequest;
|
||||
use flowy_sys::prelude::ModuleRequest;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[derive(Default, ProtoBuf)]
|
||||
@ -19,6 +19,6 @@ impl FFIRequest {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::Into<DispatchRequest> for FFIRequest {
|
||||
fn into(self) -> DispatchRequest { DispatchRequest::new(self.event).payload(self.payload) }
|
||||
impl std::convert::Into<ModuleRequest> for FFIRequest {
|
||||
fn into(self) -> ModuleRequest { ModuleRequest::new(self.event).payload(self.payload) }
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ impl ASTEnumAttrVariant {
|
||||
}
|
||||
|
||||
pub fn get_meta_items(cx: &Ctxt, attr: &syn::Attribute) -> Result<Vec<syn::NestedMeta>, ()> {
|
||||
if attr.path != PB_ATTRS {
|
||||
if attr.path != PB_ATTRS && attr.path != EVENT {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
@ -361,10 +361,11 @@ pub fn get_meta_items(cx: &Ctxt, attr: &syn::Attribute) -> Result<Vec<syn::Neste
|
||||
match attr.parse_meta() {
|
||||
Ok(List(meta)) => Ok(meta.nested.into_iter().collect()),
|
||||
Ok(other) => {
|
||||
cx.error_spanned_by(other, "expected #[pb(...)]");
|
||||
cx.error_spanned_by(other, "expected #[pb(...)] or or #[event(...)]");
|
||||
Err(())
|
||||
},
|
||||
Err(err) => {
|
||||
cx.error_spanned_by(attr, "attribute must be str, e.g. #[pb(xx = \"xxx\")]");
|
||||
cx.syn_error(err);
|
||||
Err(())
|
||||
},
|
||||
|
4
rust-lib/flowy-derive/src/dart_event/mod.rs
Normal file
4
rust-lib/flowy-derive/src/dart_event/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
use proc_macro2::TokenStream;
|
||||
pub fn expand_enum_derive(_input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> {
|
||||
Ok(TokenStream::default())
|
||||
}
|
@ -8,6 +8,7 @@ use syn::{parse_macro_input, DeriveInput};
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
|
||||
mod dart_event;
|
||||
mod derive_cache;
|
||||
mod proto_buf;
|
||||
|
||||
@ -28,6 +29,14 @@ pub fn derive_proto_buf_enum(input: TokenStream) -> TokenStream {
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Flowy_Event, attributes(event))]
|
||||
pub fn derive_dart_event(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
dart_event::expand_enum_derive(&input)
|
||||
.unwrap_or_else(to_compile_errors)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream {
|
||||
let compile_errors = errors.iter().map(syn::Error::to_compile_error);
|
||||
quote!(#(#compile_errors)*)
|
||||
|
@ -14,5 +14,3 @@ impl FlowySDK {
|
||||
EventDispatch::construct(|| build_modules());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sync_send(request: DispatchRequest) -> EventResponse { EventDispatch::sync_send(request) }
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
error::{Error, InternalError, SystemError},
|
||||
module::{as_module_map, Event, Module, ModuleMap, ModuleRequest},
|
||||
request::Payload,
|
||||
module::{as_module_map, Module, ModuleMap, ModuleRequest},
|
||||
response::EventResponse,
|
||||
service::{Service, ServiceFactory},
|
||||
util::tokio_default_runtime,
|
||||
@ -11,13 +10,7 @@ use futures_core::future::BoxFuture;
|
||||
use futures_util::task::Context;
|
||||
use lazy_static::lazy_static;
|
||||
use pin_project::pin_project;
|
||||
use std::{
|
||||
convert::TryInto,
|
||||
fmt::{Debug, Display},
|
||||
future::Future,
|
||||
hash::Hash,
|
||||
sync::RwLock,
|
||||
};
|
||||
use std::{future::Future, sync::RwLock};
|
||||
use tokio::macros::support::{Pin, Poll};
|
||||
|
||||
lazy_static! {
|
||||
@ -48,21 +41,27 @@ impl EventDispatch {
|
||||
|
||||
pub fn async_send<Req, Callback>(request: Req, callback: Callback) -> DispatchFuture
|
||||
where
|
||||
Req: std::convert::Into<DispatchRequest>,
|
||||
Req: std::convert::Into<ModuleRequest>,
|
||||
Callback: FnOnce(EventResponse) -> BoxFuture<'static, ()> + 'static + Send + Sync,
|
||||
{
|
||||
let mut request = request.into();
|
||||
request.callback = Some(Box::new(callback));
|
||||
|
||||
let request: ModuleRequest = request.into();
|
||||
match EVENT_DISPATCH.read() {
|
||||
Ok(dispatch) => {
|
||||
let dispatch = dispatch.as_ref().unwrap();
|
||||
let module_map = dispatch.module_map.clone();
|
||||
let service = Box::new(DispatchService { module_map });
|
||||
log::trace!("{}: dispatch {:?} to runtime", &request.id, &request.event);
|
||||
log::trace!(
|
||||
"{}: dispatch {:?} to runtime",
|
||||
&request.id(),
|
||||
&request.event()
|
||||
);
|
||||
let service_ctx = DispatchContext {
|
||||
request,
|
||||
callback: Some(Box::new(callback)),
|
||||
};
|
||||
let join_handle = dispatch.runtime.spawn(async move {
|
||||
service
|
||||
.call(request)
|
||||
.call(service_ctx)
|
||||
.await
|
||||
.unwrap_or_else(|e| InternalError::new(format!("{:?}", e)).as_response())
|
||||
});
|
||||
@ -87,7 +86,7 @@ impl EventDispatch {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sync_send(request: DispatchRequest) -> EventResponse {
|
||||
pub fn sync_send(request: ModuleRequest) -> EventResponse {
|
||||
futures::executor::block_on(async {
|
||||
EventDispatch::async_send(request, |response| {
|
||||
dbg!(&response);
|
||||
@ -120,49 +119,16 @@ pub type BoxFutureCallback =
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug)]
|
||||
pub struct DispatchRequest {
|
||||
pub id: String,
|
||||
pub event: Event,
|
||||
pub payload: Payload,
|
||||
pub struct DispatchContext {
|
||||
pub request: ModuleRequest,
|
||||
#[derivative(Debug = "ignore")]
|
||||
pub callback: Option<BoxFutureCallback>,
|
||||
}
|
||||
|
||||
impl DispatchRequest {
|
||||
pub fn new<E>(event: E) -> Self
|
||||
where
|
||||
E: Eq + Hash + Debug + Clone + Display,
|
||||
{
|
||||
Self {
|
||||
payload: Payload::None,
|
||||
event: event.into(),
|
||||
id: uuid::Uuid::new_v4().to_string(),
|
||||
callback: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn payload<P>(mut self, payload: P) -> Self
|
||||
where
|
||||
P: Into<Payload>,
|
||||
{
|
||||
self.payload = payload.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn callback(mut self, callback: BoxFutureCallback) -> Self {
|
||||
self.callback = Some(callback);
|
||||
self
|
||||
}
|
||||
|
||||
impl DispatchContext {
|
||||
pub(crate) fn into_parts(self) -> (ModuleRequest, Option<BoxFutureCallback>) {
|
||||
let DispatchRequest {
|
||||
event,
|
||||
payload,
|
||||
id,
|
||||
callback,
|
||||
} = self;
|
||||
|
||||
(ModuleRequest::new(event.clone(), id, payload), callback)
|
||||
let DispatchContext { request, callback } = self;
|
||||
(request, callback)
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,22 +136,19 @@ pub(crate) struct DispatchService {
|
||||
pub(crate) module_map: ModuleMap,
|
||||
}
|
||||
|
||||
impl Service<DispatchRequest> for DispatchService {
|
||||
impl Service<DispatchContext> for DispatchService {
|
||||
type Response = EventResponse;
|
||||
type Error = SystemError;
|
||||
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "use_tracing",
|
||||
tracing::instrument(
|
||||
name = "DispatchService",
|
||||
level = "debug",
|
||||
skip(self, dispatch_request)
|
||||
)
|
||||
tracing::instrument(name = "DispatchService", level = "debug", skip(self, ctx))
|
||||
)]
|
||||
fn call(&self, dispatch_request: DispatchRequest) -> Self::Future {
|
||||
fn call(&self, ctx: DispatchContext) -> Self::Future {
|
||||
let module_map = self.module_map.clone();
|
||||
let (request, callback) = dispatch_request.into_parts();
|
||||
let (request, callback) = ctx.into_parts();
|
||||
|
||||
Box::pin(async move {
|
||||
let result = {
|
||||
match module_map.get(&request.event()) {
|
||||
|
@ -113,19 +113,27 @@ pub struct ModuleRequest {
|
||||
}
|
||||
|
||||
impl ModuleRequest {
|
||||
pub fn new<E>(event: E, id: String, payload: Payload) -> Self
|
||||
pub fn new<E>(event: E) -> Self
|
||||
where
|
||||
E: Into<Event>,
|
||||
{
|
||||
Self {
|
||||
inner: EventRequest::new(event, id),
|
||||
payload,
|
||||
inner: EventRequest::new(event, uuid::Uuid::new_v4().to_string()),
|
||||
payload: Payload::None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn id(&self) -> &str { &self.inner.id }
|
||||
pub fn payload<P>(mut self, payload: P) -> Self
|
||||
where
|
||||
P: Into<Payload>,
|
||||
{
|
||||
self.payload = payload.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn event(&self) -> &Event { &self.inner.event }
|
||||
pub fn id(&self) -> &str { &self.inner.id }
|
||||
|
||||
pub fn event(&self) -> &Event { &self.inner.event }
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ModuleRequest {
|
||||
|
@ -9,14 +9,11 @@ async fn test_init() {
|
||||
let event = "1";
|
||||
init_dispatch(|| vec![Module::new().event(event, hello)]);
|
||||
|
||||
let request = DispatchRequest::new(event);
|
||||
let _ = EventDispatch::async_send(
|
||||
request,
|
||||
Some(|resp| {
|
||||
Box::pin(async move {
|
||||
dbg!(&resp);
|
||||
})
|
||||
}),
|
||||
)
|
||||
let request = ModuleRequest::new(event);
|
||||
let _ = EventDispatch::async_send(request, |resp| {
|
||||
Box::pin(async move {
|
||||
dbg!(&resp);
|
||||
})
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ fn root_dir() -> String {
|
||||
}
|
||||
|
||||
pub struct EventTester {
|
||||
request: Option<DispatchRequest>,
|
||||
request: Option<ModuleRequest>,
|
||||
assert_status_code: Option<StatusCode>,
|
||||
response: Option<EventResponse>,
|
||||
}
|
||||
@ -53,7 +53,7 @@ impl EventTester {
|
||||
E: Eq + Hash + Debug + Clone + Display,
|
||||
{
|
||||
init_sdk();
|
||||
let request = DispatchRequest::new(event);
|
||||
let request = ModuleRequest::new(event);
|
||||
Self {
|
||||
request: Some(request),
|
||||
assert_status_code: None,
|
||||
@ -91,7 +91,8 @@ impl EventTester {
|
||||
}
|
||||
|
||||
pub fn sync_send(mut self) -> Self {
|
||||
let resp = sync_send(self.request.take().unwrap());
|
||||
let resp = EventDispatch::sync_send(self.request.take().unwrap());
|
||||
|
||||
if let Some(ref status_code) = self.assert_status_code {
|
||||
assert_eq!(&resp.status_code, status_code)
|
||||
}
|
||||
@ -108,11 +109,3 @@ impl EventTester {
|
||||
<Data<R>>::try_from(response.payload).unwrap().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
fn data_from_response<R>(response: &EventResponse) -> R
|
||||
where
|
||||
R: FromBytes,
|
||||
{
|
||||
let result = <Data<R>>::try_from(&response.payload).unwrap().into_inner();
|
||||
result
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
|
||||
proto_crates = ["src/domain"]
|
||||
event_files = ["src/module.rs"]
|
||||
event_files = ["src/domain/event.rs"]
|
@ -1,10 +1,12 @@
|
||||
use derive_more::Display;
|
||||
use flowy_derive::ProtoBuf_Enum;
|
||||
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
|
||||
pub enum UserEvent {
|
||||
#[display(fmt = "AuthCheck")]
|
||||
#[event(input = "UserSignInParams", output = "UserSignInResult")]
|
||||
AuthCheck = 0,
|
||||
#[event(input = "UserSignInParams", output = "UserSignInResult")]
|
||||
#[display(fmt = "SignIn")]
|
||||
SignIn = 1,
|
||||
#[display(fmt = "SignUp")]
|
||||
@ -12,16 +14,3 @@ pub enum UserEvent {
|
||||
#[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}
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
@ -100,6 +100,7 @@ pub fn parse_event_crate(event_crate: &DartEventCrate) -> Vec<EventASTContext> {
|
||||
|
||||
pub fn ast_to_event_render_ctx(ast: &Vec<EventASTContext>) -> Vec<EventRenderContext> {
|
||||
ast.iter()
|
||||
.filter(|event_ast| event_ast.event_input.is_some() && event_ast.event_output.is_some())
|
||||
.map(|event_ast| EventRenderContext {
|
||||
input_deserializer: event_ast
|
||||
.event_input
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::util::get_tera;
|
||||
use tera::Context;
|
||||
|
||||
pub struct EventTemplate {
|
||||
@ -6,7 +7,7 @@ pub struct EventTemplate {
|
||||
|
||||
pub const DART_IMPORTED: &'static str = r#"
|
||||
/// Auto gen code from rust ast, do not edit
|
||||
part of 'cqrs.dart';
|
||||
part of 'dispatch.dart';
|
||||
"#;
|
||||
|
||||
pub struct EventRenderContext {
|
||||
@ -24,69 +25,30 @@ 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
|
||||
// }
|
||||
// }
|
||||
pub fn render(&mut self, ctx: EventRenderContext, index: usize) -> Option<String> {
|
||||
if index == 0 {
|
||||
self.tera_context
|
||||
.insert("imported_dart_files", DART_IMPORTED)
|
||||
}
|
||||
self.tera_context.insert("index", &index);
|
||||
|
||||
let dart_class_name = format!("{}{}", ctx.event_ty, ctx.event);
|
||||
let event = format!("{}.{}", ctx.event_ty, ctx.event);
|
||||
|
||||
self.tera_context.insert("event_class", &dart_class_name);
|
||||
self.tera_context.insert("event", &event);
|
||||
self.tera_context
|
||||
.insert("input_deserializer", &ctx.input_deserializer);
|
||||
self.tera_context
|
||||
.insert("output_deserializer", &ctx.output_deserializer);
|
||||
|
||||
let tera = get_tera("dart_event");
|
||||
match tera.render("event_template.tera", &self.tera_context) {
|
||||
Ok(r) => Some(r),
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,71 +2,25 @@
|
||||
{{ imported_dart_files }}
|
||||
{%- endif -%}
|
||||
|
||||
class {{ command_request_struct_ident }} {
|
||||
{%- if has_request_deserializer %}
|
||||
{{ request_deserializer }} body;
|
||||
{%- else %}
|
||||
Uint8List? body;
|
||||
{%- endif %}
|
||||
class {{ event_class }} {
|
||||
{{ input_deserializer }} params;
|
||||
{{ event_class }}(this.params);
|
||||
|
||||
{%- 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();
|
||||
Future<Either<{{ output_deserializer }}, FlowyError>> send() {
|
||||
return paramsToBytes(params).fold(
|
||||
(bytes) {
|
||||
final request = FFIRequest.create()
|
||||
..event = {{ event }}.toString()
|
||||
..payload = bytes;
|
||||
|
||||
{%- 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 %}
|
||||
});
|
||||
return Dispatch.asyncRequest(request)
|
||||
.then((bytesResult) => bytesResult.fold(
|
||||
(bytes) => left({{ output_deserializer }}.fromBuffer(bytes)),
|
||||
(error) => right(error),
|
||||
));
|
||||
},
|
||||
(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 %}
|
||||
(err) => Future(() => right(err)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ impl ProtobufDeriveMeta {
|
||||
self.context.insert("names", &self.structs);
|
||||
self.context.insert("enums", &self.enums);
|
||||
|
||||
let tera = get_tera("derive_meta");
|
||||
let tera = get_tera("proto/template/derive_meta");
|
||||
match tera.render("derive_meta.tera", &self.context) {
|
||||
Ok(r) => Some(r),
|
||||
Err(e) => {
|
||||
|
@ -26,7 +26,7 @@ impl EnumTemplate {
|
||||
|
||||
pub fn render(&mut self) -> Option<String> {
|
||||
self.context.insert("items", &self.items);
|
||||
let tera = get_tera("proto_file");
|
||||
let tera = get_tera("proto/template/proto_file");
|
||||
match tera.render("enum.tera", &self.context) {
|
||||
Ok(r) => Some(r),
|
||||
Err(e) => {
|
||||
|
@ -84,7 +84,7 @@ impl StructTemplate {
|
||||
|
||||
pub fn render(&mut self) -> Option<String> {
|
||||
self.context.insert("fields", &self.fields);
|
||||
let tera = get_tera("proto_file");
|
||||
let tera = get_tera("proto/template/proto_file");
|
||||
match tera.render("struct.tera", &self.context) {
|
||||
Ok(r) => Some(r),
|
||||
Err(e) => {
|
||||
|
@ -89,7 +89,7 @@ pub fn print_diff(old_content: String, new_content: String) {
|
||||
}
|
||||
|
||||
pub fn get_tera(directory: &str) -> Tera {
|
||||
let mut root = "./scripts/flowy-tool/src/proto/template/".to_owned();
|
||||
let mut root = "./scripts/flowy-tool/src/".to_owned();
|
||||
root.push_str(directory);
|
||||
|
||||
let root_absolute_path = std::fs::canonicalize(root)
|
||||
|
@ -5,7 +5,7 @@ dependencies = ["gen_pb_file"]
|
||||
[tasks.gen_pb_file]
|
||||
script = [
|
||||
"""
|
||||
pb_gen_bin=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/flowy-tool/Cargo.toml
|
||||
flowy_tool=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/flowy-tool/Cargo.toml
|
||||
rust_source=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
|
||||
rust_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib
|
||||
flutter_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
|
||||
@ -14,10 +14,28 @@ script = [
|
||||
flutter_package_lib=${flutter_lib}/flowy_sdk/lib
|
||||
|
||||
cargo run \
|
||||
--manifest-path ${pb_gen_bin} pb-gen \
|
||||
--manifest-path ${flowy_tool} pb-gen \
|
||||
--rust_source=${rust_source} \
|
||||
--derive_meta=${derive_meta} \
|
||||
--flutter_package_lib=${flutter_package_lib}
|
||||
""",
|
||||
]
|
||||
script_runner = "@shell"
|
||||
|
||||
|
||||
[tasks.gen_dart_event]
|
||||
script = [
|
||||
"""
|
||||
flowy_tool=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/scripts/flowy-tool/Cargo.toml
|
||||
flutter_lib=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages
|
||||
|
||||
rust_source=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/
|
||||
output=${flutter_lib}/flowy_sdk/lib/dispatch/code_gen.dart
|
||||
|
||||
cargo run \
|
||||
--manifest-path ${flowy_tool} dart-event \
|
||||
--rust_source=${rust_source} \
|
||||
--output=${output}
|
||||
""",
|
||||
]
|
||||
script_runner = "@shell"
|
||||
|
Loading…
Reference in New Issue
Block a user