Browse Source

add flowy.toml file to control protobuf generation process

appflowy 3 years ago
parent
commit
8f615fd115

+ 1 - 0
rust-lib/dart-ffi/Cargo.toml

@@ -27,6 +27,7 @@ serde_json = {version = "1.0"}
 
 flowy-sys = {path = "../flowy-sys"}
 flowy-sdk = {path = "../flowy-sdk"}
+flowy-derive = {path = "../flowy-derive"}
 
 
 #[features]

+ 1 - 0
rust-lib/dart-ffi/Flowy.toml

@@ -0,0 +1 @@
+proto_crates = ["src/model"]

+ 6 - 22
rust-lib/dart-ffi/src/lib.rs

@@ -1,6 +1,11 @@
 mod c;
+mod model;
+mod protobuf;
 
-use crate::c::{extend_front_four_bytes_into_bytes, forget_rust};
+use crate::{
+    c::{extend_front_four_bytes_into_bytes, forget_rust},
+    protobuf::FFIRequest,
+};
 use flowy_sdk::*;
 use flowy_sys::prelude::*;
 use lazy_static::lazy_static;
@@ -61,27 +66,6 @@ pub extern "C" fn sync_command(input: *const u8, len: usize) -> *const u8 {
 #[no_mangle]
 pub extern "C" fn link_me_please() {}
 
-#[derive(serde::Deserialize)]
-pub struct FFIRequest {
-    event: String,
-    payload: Vec<u8>,
-}
-
-impl FFIRequest {
-    pub fn from_u8_pointer(pointer: *const u8, len: usize) -> Self {
-        let bytes = unsafe { std::slice::from_raw_parts(pointer, len) }.to_vec();
-        let request: FFIRequest = serde_json::from_slice(&bytes).unwrap();
-        request
-    }
-}
-
-#[derive(serde::Serialize)]
-pub struct FFIResponse {
-    event: String,
-    payload: Vec<u8>,
-    error: String,
-}
-
 #[inline(always)]
 async fn spawn_future<F>(future: F, port: i64)
 where

+ 19 - 0
rust-lib/dart-ffi/src/model/ffi_request.rs

@@ -0,0 +1,19 @@
+use flowy_derive::ProtoBuf;
+use std::convert::TryFrom;
+
+#[derive(Default, ProtoBuf)]
+pub struct FFIRequest {
+    #[pb(index = 1)]
+    event: String,
+
+    #[pb(index = 2)]
+    payload: Vec<u8>,
+}
+
+impl FFIRequest {
+    pub fn from_u8_pointer(pointer: *const u8, len: usize) -> Self {
+        let bytes = unsafe { std::slice::from_raw_parts(pointer, len) }.to_vec();
+        let request: FFIRequest = FFIRequest::try_from(&bytes).unwrap();
+        request
+    }
+}

+ 13 - 0
rust-lib/dart-ffi/src/model/ffi_response.rs

@@ -0,0 +1,13 @@
+use flowy_derive::ProtoBuf;
+
+#[derive(ProtoBuf, Default)]
+pub struct FFIResponse {
+    #[pb(index = 1)]
+    event: String,
+
+    #[pb(index = 2)]
+    payload: Vec<u8>,
+
+    #[pb(index = 3)]
+    error: String,
+}

+ 5 - 0
rust-lib/dart-ffi/src/model/mod.rs

@@ -0,0 +1,5 @@
+mod ffi_request;
+mod ffi_response;
+
+pub use ffi_request::*;
+pub use ffi_response::*;

+ 4 - 0
rust-lib/dart-ffi/src/protobuf/mod.rs

@@ -0,0 +1,4 @@
+
+mod model;
+pub use model::*;
+        

+ 250 - 0
rust-lib/dart-ffi/src/protobuf/model/ffi_request.rs

@@ -0,0 +1,250 @@
+// 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 `ffi_request.proto`
+
+/// Generated files are compatible only with the same version
+/// of protobuf runtime.
+// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
+
+#[derive(PartialEq,Clone,Default)]
+pub struct FFIRequest {
+    // message fields
+    pub event: ::std::string::String,
+    pub payload: ::std::vec::Vec<u8>,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a FFIRequest {
+    fn default() -> &'a FFIRequest {
+        <FFIRequest as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl FFIRequest {
+    pub fn new() -> FFIRequest {
+        ::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;
+
+
+    pub fn get_payload(&self) -> &[u8] {
+        &self.payload
+    }
+    pub fn clear_payload(&mut self) {
+        self.payload.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_payload(&mut self, v: ::std::vec::Vec<u8>) {
+        self.payload = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_payload(&mut self) -> &mut ::std::vec::Vec<u8> {
+        &mut self.payload
+    }
+
+    // Take field
+    pub fn take_payload(&mut self) -> ::std::vec::Vec<u8> {
+        ::std::mem::replace(&mut self.payload, ::std::vec::Vec::new())
+    }
+}
+
+impl ::protobuf::Message for FFIRequest {
+    fn is_initialized(&self) -> bool {
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            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)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[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::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    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_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> FFIRequest {
+        FFIRequest::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        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: &FFIRequest| { &m.event },
+                |m: &mut FFIRequest| { &mut m.event },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
+                "payload",
+                |m: &FFIRequest| { &m.payload },
+                |m: &mut FFIRequest| { &mut m.payload },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<FFIRequest>(
+                "FFIRequest",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static FFIRequest {
+        static instance: ::protobuf::rt::LazyV2<FFIRequest> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(FFIRequest::new)
+    }
+}
+
+impl ::protobuf::Clear for FFIRequest {
+    fn clear(&mut self) {
+        self.event.clear();
+        self.payload.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for FFIRequest {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for FFIRequest {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+    \n\x11ffi_request.proto\"<\n\nFFIRequest\x12\x14\n\x05event\x18\x01\x20\
+    \x01(\tR\x05event\x12\x18\n\x07payload\x18\x02\x20\x01(\x0cR\x07payloadJ\
+    \x98\x01\n\x06\x12\x04\0\0\x05\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\x12\
+    \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\x15b\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()
+    })
+}

+ 295 - 0
rust-lib/dart-ffi/src/protobuf/model/ffi_response.rs

@@ -0,0 +1,295 @@
+// 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 `ffi_response.proto`
+
+/// Generated files are compatible only with the same version
+/// of protobuf runtime.
+// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
+
+#[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,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a FFIResponse {
+    fn default() -> &'a FFIResponse {
+        <FFIResponse as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl FFIResponse {
+    pub fn new() -> 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;
+
+
+    pub fn get_payload(&self) -> &[u8] {
+        &self.payload
+    }
+    pub fn clear_payload(&mut self) {
+        self.payload.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_payload(&mut self, v: ::std::vec::Vec<u8>) {
+        self.payload = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_payload(&mut self) -> &mut ::std::vec::Vec<u8> {
+        &mut self.payload
+    }
+
+    // Take field
+    pub fn take_payload(&mut self) -> ::std::vec::Vec<u8> {
+        ::std::mem::replace(&mut self.payload, ::std::vec::Vec::new())
+    }
+
+    // string error = 3;
+
+
+    pub fn get_error(&self) -> &str {
+        &self.error
+    }
+    pub fn clear_error(&mut self) {
+        self.error.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_error(&mut self, v: ::std::string::String) {
+        self.error = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_error(&mut self) -> &mut ::std::string::String {
+        &mut self.error
+    }
+
+    // Take field
+    pub fn take_error(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.error, ::std::string::String::new())
+    }
+}
+
+impl ::protobuf::Message for FFIResponse {
+    fn is_initialized(&self) -> bool {
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            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 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.error)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[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);
+        }
+        if !self.error.is_empty() {
+            my_size += ::protobuf::rt::string_size(3, &self.error);
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    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)?;
+        }
+        if !self.error.is_empty() {
+            os.write_string(3, &self.error)?;
+        }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> FFIResponse {
+        FFIResponse::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        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 },
+                |m: &mut FFIResponse| { &mut m.payload },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "error",
+                |m: &FFIResponse| { &m.error },
+                |m: &mut FFIResponse| { &mut m.error },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<FFIResponse>(
+                "FFIResponse",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static FFIResponse {
+        static instance: ::protobuf::rt::LazyV2<FFIResponse> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(FFIResponse::new)
+    }
+}
+
+impl ::protobuf::Clear for FFIResponse {
+    fn clear(&mut self) {
+        self.event.clear();
+        self.payload.clear();
+        self.error.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for FFIResponse {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for FFIResponse {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(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\x05\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\
+    \x01\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x01\x08\x13\n\x0b\n\x04\x04\0\
+    \x02\0\x12\x03\x02\x04\x15\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x02\x04\n\
+    \n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x02\x0b\x10\n\x0c\n\x05\x04\0\x02\0\
+    \x03\x12\x03\x02\x13\x14\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x03\x04\x16\n\
+    \x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x03\x04\t\n\x0c\n\x05\x04\0\x02\x01\
+    \x01\x12\x03\x03\n\x11\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x03\x14\x15\
+    \n\x0b\n\x04\x04\0\x02\x02\x12\x03\x04\x04\x15\n\x0c\n\x05\x04\0\x02\x02\
+    \x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x04\x0b\x10\
+    \n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x04\x13\x14b\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()
+    })
+}

+ 6 - 0
rust-lib/dart-ffi/src/protobuf/model/mod.rs

@@ -0,0 +1,6 @@
+
+mod ffi_response; 
+pub use ffi_response::*; 
+
+mod ffi_request; 
+pub use ffi_request::*; 

+ 6 - 0
rust-lib/dart-ffi/src/protobuf/proto/ffi_request.proto

@@ -0,0 +1,6 @@
+syntax = "proto3";
+
+message FFIRequest {
+    string event = 1;
+    bytes payload = 2;
+}

+ 6 - 0
rust-lib/dart-ffi/src/protobuf/proto/ffi_response.proto

@@ -0,0 +1,6 @@
+syntax = "proto3";
+message FFIResponse {
+    string event = 1;
+    bytes payload = 2;
+    string error = 3;
+}

+ 3 - 1
rust-lib/flowy-derive/src/derive_cache/derive_cache.rs

@@ -15,7 +15,9 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         "HashMap" => TypeCategory::Map,
         "u8" => TypeCategory::Bytes,
         "String" => TypeCategory::Str,
-        "User"
+        "FFIRequest"
+        | "FFIResponse"
+        | "User"
         | "UserSignUpParams"
         | "UserSignUpRequest"
         | "UserSignUpResult"

+ 1 - 1
rust-lib/flowy-sdk/tests/sdk/user/sign_in.rs

@@ -6,7 +6,7 @@ use std::convert::{TryFrom, TryInto};
 #[test]
 fn sign_in_without_password() {
     let params = UserSignInParams {
-        email: "a[email protected]".to_string(),
+        email: "a[email protected]".to_string(),
         password: "".to_string(),
     };
     let bytes: Vec<u8> = params.try_into().unwrap();

+ 2 - 0
rust-lib/flowy-user/Flowy.toml

@@ -0,0 +1,2 @@
+
+proto_crates = ["src/domain"]

+ 3 - 1
scripts/flowy-tool/Cargo.toml

@@ -20,4 +20,6 @@ fancy-regex = "0.5.0"
 lazy_static = "1.4.0"
 phf = { version = "0.8.0", features = ["macros"] }
 similar = "1.2.2"
-dialoguer = "0.8.0"
+dialoguer = "0.8.0"
+toml = "0.5.8"
+serde = { version = "1.0", features = ["derive"] }

+ 14 - 0
scripts/flowy-tool/src/config/mod.rs

@@ -0,0 +1,14 @@
+use std::fs;
+
+#[derive(serde::Deserialize)]
+pub struct FlowyConfig {
+    pub proto_crates: Vec<String>,
+}
+
+impl FlowyConfig {
+    pub fn from_toml_file(path: &str) -> Self {
+        let content = fs::read_to_string(path).unwrap();
+        let config: FlowyConfig = toml::from_str(content.as_ref()).unwrap();
+        config
+    }
+}

+ 2 - 1
scripts/flowy-tool/src/main.rs

@@ -1,10 +1,11 @@
+mod config;
 mod proto;
 mod util;
 
 use clap::{App, Arg};
 
 fn main() {
-    std::env::set_var("RUST_LOG", "Debug");
+    std::env::set_var("RUST_LOG", "Info");
     env_logger::init();
 
     let matches = app().get_matches();

+ 10 - 6
scripts/flowy-tool/src/proto/ast.rs

@@ -10,19 +10,23 @@ pub fn parse_crate_protobuf(root: &str) -> Vec<CrateProtoInfo> {
     domains_info
         .into_iter()
         .map(|crate_info| {
-            let files = parse_files_protobuf(&crate_info);
+            let proto_output_dir = crate_info.proto_file_output_dir();
+            let files = crate_info
+                .proto_crate_paths
+                .iter()
+                .map(|proto_crate_path| parse_files_protobuf(proto_crate_path, &proto_output_dir))
+                .flatten()
+                .collect::<Vec<FileProtoInfo>>();
+
             CrateProtoInfo::from_crate_info(crate_info, files)
         })
         .collect::<Vec<CrateProtoInfo>>()
 }
 
-fn parse_files_protobuf(crate_info: &CrateInfo) -> Vec<FileProtoInfo> {
+fn parse_files_protobuf(proto_crate_path: &str, proto_output_dir: &str) -> Vec<FileProtoInfo> {
     let mut gen_proto_vec: Vec<FileProtoInfo> = vec![];
-    let root = crate_info.domain_path.as_str();
-    let proto_output_dir = crate_info.proto_file_output_dir();
-
     // file_stem https://doc.rust-lang.org/std/path/struct.Path.html#method.file_stem
-    for (path, file_name) in WalkDir::new(root)
+    for (path, file_name) in WalkDir::new(proto_crate_path)
         .into_iter()
         .filter_entry(|e| !is_hidden(e))
         .filter_map(|e| e.ok())

+ 1 - 2
scripts/flowy-tool/src/proto/builder.rs

@@ -1,5 +1,6 @@
 use crate::proto::ProtoGen;
 
+#[allow(dead_code)]
 pub struct ProtoGenBuilder {
     rust_source_dir: Option<String>,
     proto_file_output_dir: Option<String>,
@@ -47,8 +48,6 @@ impl ProtoGenBuilder {
     pub fn build(self) -> ProtoGen {
         ProtoGen {
             rust_source_dir: self.rust_source_dir.unwrap(),
-            proto_file_output_dir: self.proto_file_output_dir.unwrap(),
-            rust_mod_dir: self.rust_mod_dir.unwrap(),
             flutter_mod_dir: self.flutter_mod_dir.unwrap(),
             derive_meta_dir: self.derive_meta_dir.unwrap(),
         }

+ 13 - 22
scripts/flowy-tool/src/proto/helper.rs

@@ -1,3 +1,4 @@
+use crate::config::*;
 use std::fs::OpenOptions;
 use std::io::Write;
 use walkdir::WalkDir;
@@ -5,7 +6,7 @@ use walkdir::WalkDir;
 #[derive(Clone)]
 pub struct CrateInfo {
     pub crate_folder_name: String,
-    pub domain_path: String,
+    pub proto_crate_paths: Vec<String>,
     pub crate_path: String,
 }
 
@@ -89,13 +90,21 @@ pub fn get_crate_domain_directory(root: &str) -> Vec<CrateInfo> {
         .flat_map(|e| {
             // Assert e.path().parent() will be the crate dir
             let path = e.path().parent().unwrap();
+            let crate_path = path.to_str().unwrap().to_string();
             let crate_folder_name = path.file_stem().unwrap().to_str().unwrap().to_string();
-            if crate_folder_name == "flowy-user".to_owned() {
+            let flowy_config_file = format!("{}/Flowy.toml", crate_path);
+
+            if std::path::Path::new(&flowy_config_file).exists() {
+                let config = FlowyConfig::from_toml_file(flowy_config_file.as_ref());
                 let crate_path = path.to_str().unwrap().to_string();
-                let domain_path = format!("{}/src/domain", crate_path);
+                let proto_crate_paths = config
+                    .proto_crates
+                    .iter()
+                    .map(|name| format!("{}/{}", crate_path, name))
+                    .collect::<Vec<String>>();
                 Some(CrateInfo {
                     crate_folder_name,
-                    domain_path,
+                    proto_crate_paths,
                     crate_path,
                 })
             } else {
@@ -105,29 +114,11 @@ pub fn get_crate_domain_directory(root: &str) -> Vec<CrateInfo> {
         .collect::<Vec<CrateInfo>>()
 }
 
-pub fn is_domain_dir(e: &walkdir::DirEntry) -> bool {
-    let domain = e.path().file_stem().unwrap().to_str().unwrap().to_string();
-    if e.file_type().is_dir() && domain == "domain".to_string() {
-        true
-    } else {
-        false
-    }
-}
-
 pub fn is_crate_dir(e: &walkdir::DirEntry) -> bool {
     let cargo = e.path().file_stem().unwrap().to_str().unwrap().to_string();
     cargo == "Cargo".to_string()
 }
 
-pub fn domain_dir_from(e: &walkdir::DirEntry) -> Option<String> {
-    let domain = e.path().file_stem().unwrap().to_str().unwrap().to_string();
-    if e.file_type().is_dir() && domain == "domain".to_string() {
-        Some(e.path().to_str().unwrap().to_string())
-    } else {
-        None
-    }
-}
-
 pub fn is_proto_file(e: &walkdir::DirEntry) -> bool {
     if e.path().extension().is_none() {
         return false;

+ 0 - 2
scripts/flowy-tool/src/proto/proto_gen.rs

@@ -8,8 +8,6 @@ use walkdir::WalkDir;
 
 pub struct ProtoGen {
     pub(crate) rust_source_dir: String,
-    pub(crate) proto_file_output_dir: String,
-    pub(crate) rust_mod_dir: String,
     pub(crate) flutter_mod_dir: String,
     pub(crate) derive_meta_dir: String,
 }