config protobuf serialize

This commit is contained in:
appflowy 2021-07-05 16:54:41 +08:00
parent 447b5aa128
commit 2d9c7ba48e
12 changed files with 537 additions and 189 deletions

View File

@ -15,7 +15,8 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
"HashMap" => TypeCategory::Map,
"u8" => TypeCategory::Bytes,
"String" => TypeCategory::Str,
"App"
"User"
| "UserCheck"
=> TypeCategory::Protobuf,
"Option" => TypeCategory::Opt,

View File

@ -1,7 +1,13 @@
mod deserialize;
mod enum_serde;
mod serialize;
mod util;
use crate::proto_buf::{deserialize::make_de_token_steam, enum_serde::make_enum_token_stream};
use crate::proto_buf::{
deserialize::make_de_token_steam,
enum_serde::make_enum_token_stream,
serialize::make_se_token_stream,
};
use flowy_ast::*;
use proc_macro2::TokenStream;
@ -19,6 +25,11 @@ pub fn expand_derive(input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::E
token_stream.extend(de_token_stream.unwrap());
}
let se_token_stream = make_se_token_stream(&ctxt, &cont);
if se_token_stream.is_some() {
token_stream.extend(se_token_stream.unwrap());
}
ctxt.check()?;
Ok(token_stream)
}

View File

@ -0,0 +1,166 @@
use crate::{derive_cache::TypeCategory, proto_buf::util::ident_category};
use flowy_ast::*;
use proc_macro2::TokenStream;
pub fn make_se_token_stream(ctxt: &Ctxt, ast: &ASTContainer) -> Option<TokenStream> {
let pb_ty = ast.attrs.pb_struct_type()?;
let struct_ident = &ast.ident;
let build_set_pb_fields = ast
.data
.all_fields()
.filter(|f| !f.attrs.skip_serializing())
.flat_map(|field| se_token_stream_for_field(&ctxt, &field, false));
let build_set_fields = ast
.data
.all_fields()
.filter(|f| !f.attrs.skip_serializing())
.flat_map(|field| se_token_stream_for_field(&ctxt, &field, false));
let se_token_stream: TokenStream = quote! {
impl std::convert::TryInto<Vec<u8>> for #struct_ident {
type Error = String;
fn try_into(self) -> Result<Vec<u8>, Self::Error> {
use protobuf::Message;
let pb: crate::protobuf::#pb_ty = self.try_into()?;
let result: ::protobuf::ProtobufResult<Vec<u8>> = pb.write_to_bytes();
match result {
Ok(bytes) => { Ok(bytes) },
Err(e) => { Err(format!("{:?}", e)) }
}
}
}
impl std::convert::TryInto<crate::protobuf::#pb_ty> for #struct_ident {
type Error = String;
fn try_into(self) -> Result<crate::protobuf::#pb_ty, Self::Error> {
let mut pb = crate::protobuf::#pb_ty::new();
#(#build_set_pb_fields)*
Ok(pb)
}
}
}
.into();
Some(se_token_stream)
}
fn se_token_stream_for_field(ctxt: &Ctxt, field: &ASTField, _take: bool) -> Option<TokenStream> {
if let Some(func) = &field.attrs.serialize_with() {
let member = &field.member;
Some(quote! { pb.#member=self.#func(); })
} else if field.attrs.is_one_of() {
let member = &field.member;
match &field.member {
syn::Member::Named(ref ident) => {
let set_func = format_ident!("set_{}", ident.to_string());
Some(quote! {
match self.#member {
Some(ref s) => { pb.#set_func(s.to_protobuf()) }
None => {}
}
})
},
_ => {
ctxt.error_spanned_by(member, format!("Unsupported member, get member ident fail"));
None
},
}
} else {
gen_token_stream(ctxt, &field.member, &field.ty, false)
}
}
fn gen_token_stream(
ctxt: &Ctxt,
member: &syn::Member,
ty: &syn::Type,
is_option: bool,
) -> Option<TokenStream> {
let ty_info = parse_ty(ctxt, ty)?;
match ident_category(ty_info.ident) {
TypeCategory::Array => token_stream_for_vec(ctxt, &member, &ty_info.ty),
TypeCategory::Map => {
token_stream_for_map(ctxt, &member, &ty_info.bracket_ty_info.unwrap().ty)
},
TypeCategory::Str => {
if is_option {
Some(quote! {
match self.#member {
Some(ref s) => { pb.#member = s.to_string().clone(); }
None => { pb.#member = String::new(); }
}
})
} else {
Some(quote! { pb.#member = self.#member.clone(); })
}
},
TypeCategory::Protobuf => Some(
quote! { pb.#member = ::protobuf::SingularPtrField::some(self.#member.to_protobuf()); },
),
TypeCategory::Opt => {
gen_token_stream(ctxt, member, ty_info.bracket_ty_info.unwrap().ty, true)
},
TypeCategory::Enum => {
// let pb_enum_ident = format_ident!("{}", ty_info.ident.to_string());
// Some(quote! {
// flowy_protobuf::#pb_enum_ident::from_i32(self.#member.value()).unwrap();
// })
Some(quote! {
pb.#member = self.#member.to_protobuf();
})
},
_ => Some(quote! { pb.#member = self.#member; }),
}
}
// e.g. pub cells: Vec<CellData>, the memeber will be cells, ty would be Vec
fn token_stream_for_vec(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Option<TokenStream> {
let ty_info = parse_ty(ctxt, ty)?;
match ident_category(ty_info.ident) {
TypeCategory::Protobuf => Some(quote! {
pb.#member = ::protobuf::RepeatedField::from_vec(
self.#member
.iter()
.map(|m| m.to_protobuf())
.collect());
}),
TypeCategory::Bytes => Some(quote! { pb.#member = self.#member.clone(); }),
_ => Some(quote! {
pb.#member = ::protobuf::RepeatedField::from_vec(self.#member.clone());
}),
}
}
// e.g. pub cells: HashMap<xx, xx>
fn token_stream_for_map(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Option<TokenStream> {
// The key of the hashmap must be string
let flowy_protobuf = format_ident!("flowy_protobuf");
let ty_info = parse_ty(ctxt, ty)?;
match ident_category(ty_info.ident) {
TypeCategory::Protobuf => {
let value_type = ty_info.ident;
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());
});
pb.#member = m;
})
},
_ => {
let value_type = ty_info.ident;
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.clone());
});
pb.#member = m;
})
},
}
}

View File

@ -35,6 +35,7 @@ tokio = { version = "1", features = ["full"] }
futures-util = "0.3.15"
[features]
default = ["use_protobuf"]
use_serde = ["bincode"]
use_protobuf= ["protobuf"]
use_tracing= ["tracing"]

View File

@ -117,16 +117,16 @@ impl<T> ops::DerefMut for Data<T> {
}
pub trait FromBytes: Sized {
fn parse_from_bytes(bytes: &Vec<u8>) -> Result<Self, SystemError>;
fn parse_from_bytes(bytes: &Vec<u8>) -> Result<Self, String>;
}
#[cfg(not(feature = "use_serde"))]
#[cfg(feature = "use_protobuf")]
impl<T> FromBytes for T
where
// https://stackoverflow.com/questions/62871045/tryfromu8-trait-bound-in-trait
T: for<'a> std::convert::TryFrom<&'a Vec<u8>, Error = SystemError>,
T: for<'a> std::convert::TryFrom<&'a Vec<u8>, Error = String>,
{
fn parse_from_bytes(bytes: &Vec<u8>) -> Result<Self, SystemError> { T::try_from(bytes) }
fn parse_from_bytes(bytes: &Vec<u8>) -> Result<Self, String> { T::try_from(bytes) }
}
#[cfg(feature = "use_serde")]
@ -134,11 +134,11 @@ impl<T> FromBytes for T
where
T: serde::de::DeserializeOwned + 'static,
{
fn parse_from_bytes(bytes: &Vec<u8>) -> Result<Self, SystemError> {
fn parse_from_bytes(bytes: &Vec<u8>) -> Result<Self, String> {
let s = String::from_utf8_lossy(bytes);
match serde_json::from_str::<T>(s.as_ref()) {
Ok(data) => Ok(data),
Err(e) => InternalError::new(format!("{:?}", e)).into(),
Err(e) => Err(format!("{:?}", e)),
}
}
}

View File

@ -39,15 +39,15 @@ where
}
pub trait ToBytes {
fn into_bytes(self) -> Result<Vec<u8>, SystemError>;
fn into_bytes(self) -> Result<Vec<u8>, String>;
}
#[cfg(not(feature = "use_serde"))]
#[cfg(feature = "use_protobuf")]
impl<T> ToBytes for T
where
T: std::convert::TryInto<Vec<u8>, Error = SystemError>,
T: std::convert::TryInto<Vec<u8>, Error = String>,
{
fn into_bytes(self) -> Result<Vec<u8>, SystemError> { self.try_into() }
fn into_bytes(self) -> Result<Vec<u8>, String> { self.try_into() }
}
#[cfg(feature = "use_serde")]
@ -55,10 +55,10 @@ impl<T> ToBytes for T
where
T: serde::Serialize,
{
fn into_bytes(self) -> Result<Vec<u8>, SystemError> {
fn into_bytes(self) -> Result<Vec<u8>, String> {
match serde_json::to_string(&self.0) {
Ok(s) => Ok(s.into_bytes()),
Err(e) => InternalError::new(format!("{:?}", e)).into(),
Err(e) => Err(format!("{:?}", e)),
}
}
}
@ -70,7 +70,10 @@ where
fn respond_to(self, _request: &EventRequest) -> EventResponse {
match self.into_inner().into_bytes() {
Ok(bytes) => ResponseBuilder::Ok().data(bytes.to_vec()).build(),
Err(e) => e.into(),
Err(e) => {
let system_err: SystemError = InternalError::new(format!("{:?}", e)).into();
system_err.into()
},
}
}
}

View File

@ -1,23 +1,57 @@
use crate::domain::{user_email::UserEmail, user_name::UserName};
use flowy_derive::ProtoBuf;
use std::convert::TryInto;
#[derive(ProtoBuf, Default)]
pub struct User {
name: UserName,
email: UserEmail,
#[pb(index = 1)]
name: String,
#[pb(index = 2)]
email: String,
}
impl User {
pub fn new(name: UserName, email: UserEmail) -> Self { Self { name, email } }
pub fn new(name: UserName, email: UserEmail) -> Self {
Self {
name: name.0,
email: email.0,
}
}
}
#[derive(ProtoBuf, Default)]
pub struct App {
// #[derive(serde::Serialize)]
// pub struct UserStatus {
// is_login: bool,
// }
//
// impl FromBytes for UserData {
// fn parse_from_bytes(_bytes: &Vec<u8>) -> Result<UserData, SystemError> {
// unimplemented!() } }
//
// impl ToBytes for UserStatus {
// fn into_bytes(self) -> Result<Vec<u8>, SystemError> { unimplemented!() }
// }
#[derive(Debug, ProtoBuf, Default)]
pub struct UserCheck {
#[pb(index = 1)]
pub id: String,
pub name: String,
#[pb(index = 2)]
pub workspace_id: String, // equal to #[belongs_to(Workspace, foreign_key = "workspace_id")].
#[pb(index = 3)]
pub name: String,
pub email: String,
}
impl UserCheck {
pub fn new(name: String, email: String) -> Self { Self { name, email } }
}
impl TryInto<User> for UserCheck {
type Error = String;
fn try_into(self) -> Result<User, Self::Error> {
let name = UserName::parse(self.name)?;
let email = UserEmail::parse(self.email)?;
Ok(User::new(name, email))
}
}

View File

@ -1,7 +1,7 @@
use validator::validate_email;
#[derive(Debug)]
pub struct UserEmail(String);
pub struct UserEmail(pub String);
impl UserEmail {
pub fn parse(s: String) -> Result<UserEmail, String> {
@ -23,7 +23,6 @@ mod tests {
use claim::assert_err;
use fake::{faker::internet::en::SafeEmail, Fake};
#[test]
fn empty_string_is_rejected() {
let email = "".to_string();

View File

@ -1,7 +1,7 @@
use unicode_segmentation::UnicodeSegmentation;
#[derive(Debug)]
pub struct UserName(String);
pub struct UserName(pub String);
impl UserName {
pub fn parse(s: String) -> Result<UserName, String> {

View File

@ -1,6 +1,5 @@
use crate::domain::{User, UserEmail, UserName};
use flowy_sys::prelude::{response_ok, Data, FromBytes, ResponseResult, SystemError, ToBytes};
use crate::domain::{User, UserCheck, UserEmail, UserName};
use flowy_sys::prelude::*;
use std::convert::TryInto;
// tracing instrument 👉🏻 https://docs.rs/tracing/0.1.26/tracing/attr.instrument.html
@ -12,41 +11,8 @@ use std::convert::TryInto;
name = %data.name
)
)]
pub async fn user_check(data: Data<UserData>) -> ResponseResult<UserStatus, String> {
let _user: User = data.into_inner().try_into()?;
pub async fn user_check(data: Data<UserCheck>) -> ResponseResult<User, String> {
let user: User = data.into_inner().try_into().unwrap();
response_ok(UserStatus { is_login: false })
}
#[derive(serde::Serialize)]
pub struct UserStatus {
is_login: bool,
}
impl FromBytes for UserData {
fn parse_from_bytes(_bytes: &Vec<u8>) -> Result<UserData, SystemError> { unimplemented!() }
}
impl ToBytes for UserStatus {
fn into_bytes(self) -> Result<Vec<u8>, SystemError> { unimplemented!() }
}
#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct UserData {
name: String,
email: String,
}
impl UserData {
pub fn new(name: String, email: String) -> Self { Self { name, email } }
}
impl TryInto<User> for UserData {
type Error = String;
fn try_into(self) -> Result<User, Self::Error> {
let name = UserName::parse(self.name)?;
let email = UserEmail::parse(self.email)?;
Ok(User::new(name, email))
}
response_ok(user)
}

View File

@ -24,80 +24,27 @@
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
#[derive(PartialEq,Clone,Default)]
pub struct App {
pub struct User {
// message fields
pub id: ::std::string::String,
pub workspace_id: ::std::string::String,
pub name: ::std::string::String,
pub email: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a App {
fn default() -> &'a App {
<App as ::protobuf::Message>::default_instance()
impl<'a> ::std::default::Default for &'a User {
fn default() -> &'a User {
<User as ::protobuf::Message>::default_instance()
}
}
impl App {
pub fn new() -> App {
impl User {
pub fn new() -> User {
::std::default::Default::default()
}
// string id = 1;
pub fn get_id(&self) -> &str {
&self.id
}
pub fn clear_id(&mut self) {
self.id.clear();
}
// Param is passed by value, moved
pub fn set_id(&mut self, v: ::std::string::String) {
self.id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_id(&mut self) -> &mut ::std::string::String {
&mut self.id
}
// Take field
pub fn take_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.id, ::std::string::String::new())
}
// string workspace_id = 2;
pub fn get_workspace_id(&self) -> &str {
&self.workspace_id
}
pub fn clear_workspace_id(&mut self) {
self.workspace_id.clear();
}
// Param is passed by value, moved
pub fn set_workspace_id(&mut self, v: ::std::string::String) {
self.workspace_id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_workspace_id(&mut self) -> &mut ::std::string::String {
&mut self.workspace_id
}
// Take field
pub fn take_workspace_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.workspace_id, ::std::string::String::new())
}
// string name = 3;
// string name = 1;
pub fn get_name(&self) -> &str {
@ -122,9 +69,35 @@ impl App {
pub fn take_name(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.name, ::std::string::String::new())
}
// string email = 2;
pub fn get_email(&self) -> &str {
&self.email
}
pub fn clear_email(&mut self) {
self.email.clear();
}
impl ::protobuf::Message for App {
// Param is passed by value, moved
pub fn set_email(&mut self, v: ::std::string::String) {
self.email = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_email(&mut self) -> &mut ::std::string::String {
&mut self.email
}
// Take field
pub fn take_email(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.email, ::std::string::String::new())
}
}
impl ::protobuf::Message for User {
fn is_initialized(&self) -> bool {
true
}
@ -134,13 +107,10 @@ impl ::protobuf::Message for App {
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.id)?;
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?;
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.workspace_id)?;
},
3 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?;
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.email)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@ -154,14 +124,11 @@ impl ::protobuf::Message for App {
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.id.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.id);
}
if !self.workspace_id.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.workspace_id);
}
if !self.name.is_empty() {
my_size += ::protobuf::rt::string_size(3, &self.name);
my_size += ::protobuf::rt::string_size(1, &self.name);
}
if !self.email.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.email);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
@ -169,14 +136,11 @@ impl ::protobuf::Message for App {
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.id.is_empty() {
os.write_string(1, &self.id)?;
}
if !self.workspace_id.is_empty() {
os.write_string(2, &self.workspace_id)?;
}
if !self.name.is_empty() {
os.write_string(3, &self.name)?;
os.write_string(1, &self.name)?;
}
if !self.email.is_empty() {
os.write_string(2, &self.email)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
@ -208,78 +172,278 @@ impl ::protobuf::Message for App {
Self::descriptor_static()
}
fn new() -> App {
App::new()
fn new() -> User {
User::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>(
"id",
|m: &App| { &m.id },
|m: &mut App| { &mut m.id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"workspace_id",
|m: &App| { &m.workspace_id },
|m: &mut App| { &mut m.workspace_id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"name",
|m: &App| { &m.name },
|m: &mut App| { &mut m.name },
|m: &User| { &m.name },
|m: &mut User| { &mut m.name },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<App>(
"App",
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"email",
|m: &User| { &m.email },
|m: &mut User| { &mut m.email },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<User>(
"User",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static App {
static instance: ::protobuf::rt::LazyV2<App> = ::protobuf::rt::LazyV2::INIT;
instance.get(App::new)
fn default_instance() -> &'static User {
static instance: ::protobuf::rt::LazyV2<User> = ::protobuf::rt::LazyV2::INIT;
instance.get(User::new)
}
}
impl ::protobuf::Clear for App {
impl ::protobuf::Clear for User {
fn clear(&mut self) {
self.id.clear();
self.workspace_id.clear();
self.name.clear();
self.email.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for App {
impl ::std::fmt::Debug for User {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for App {
impl ::protobuf::reflect::ProtobufValue for User {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(PartialEq,Clone,Default)]
pub struct UserCheck {
// message fields
pub name: ::std::string::String,
pub email: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a UserCheck {
fn default() -> &'a UserCheck {
<UserCheck as ::protobuf::Message>::default_instance()
}
}
impl UserCheck {
pub fn new() -> UserCheck {
::std::default::Default::default()
}
// string name = 1;
pub fn get_name(&self) -> &str {
&self.name
}
pub fn clear_name(&mut self) {
self.name.clear();
}
// Param is passed by value, moved
pub fn set_name(&mut self, v: ::std::string::String) {
self.name = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_name(&mut self) -> &mut ::std::string::String {
&mut self.name
}
// Take field
pub fn take_name(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.name, ::std::string::String::new())
}
// string email = 2;
pub fn get_email(&self) -> &str {
&self.email
}
pub fn clear_email(&mut self) {
self.email.clear();
}
// Param is passed by value, moved
pub fn set_email(&mut self, v: ::std::string::String) {
self.email = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_email(&mut self) -> &mut ::std::string::String {
&mut self.email
}
// Take field
pub fn take_email(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.email, ::std::string::String::new())
}
}
impl ::protobuf::Message for UserCheck {
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.name)?;
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.email)?;
},
_ => {
::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.name.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.name);
}
if !self.email.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.email);
}
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.name.is_empty() {
os.write_string(1, &self.name)?;
}
if !self.email.is_empty() {
os.write_string(2, &self.email)?;
}
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() -> UserCheck {
UserCheck::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>(
"name",
|m: &UserCheck| { &m.name },
|m: &mut UserCheck| { &mut m.name },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"email",
|m: &UserCheck| { &m.email },
|m: &mut UserCheck| { &mut m.email },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<UserCheck>(
"UserCheck",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static UserCheck {
static instance: ::protobuf::rt::LazyV2<UserCheck> = ::protobuf::rt::LazyV2::INIT;
instance.get(UserCheck::new)
}
}
impl ::protobuf::Clear for UserCheck {
fn clear(&mut self) {
self.name.clear();
self.email.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for UserCheck {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for UserCheck {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\nuser.proto\"L\n\x03App\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\
!\n\x0cworkspace_id\x18\x02\x20\x01(\tR\x0bworkspaceId\x12\x12\n\x04name\
\x18\x03\x20\x01(\tR\x04nameJ\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\x0b\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\
\x12\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\
\0\x01\x12\x03\x03\x0b\r\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\
\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x1c\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\x17\
\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x1a\x1b\n\x0b\n\x04\x04\0\x02\
\x02\x12\x03\x05\x04\x14\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\n\
\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x0b\x0f\n\x0c\n\x05\x04\0\x02\
\x02\x03\x12\x03\x05\x12\x13b\x06proto3\
\n\nuser.proto\"0\n\x04User\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04nam\
e\x12\x14\n\x05email\x18\x02\x20\x01(\tR\x05email\"5\n\tUserCheck\x12\
\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x14\n\x05email\x18\x02\
\x20\x01(\tR\x05emailJ\x9e\x02\n\x06\x12\x04\0\0\t\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\x0c\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x14\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\x0f\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x12\x13\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\n\n\x02\x04\x01\x12\
\x04\x06\0\t\x01\n\n\n\x03\x04\x01\x01\x12\x03\x06\x08\x11\n\x0b\n\x04\
\x04\x01\x02\0\x12\x03\x07\x04\x14\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\
\x07\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x07\x0b\x0f\n\x0c\n\x05\
\x04\x01\x02\0\x03\x12\x03\x07\x12\x13\n\x0b\n\x04\x04\x01\x02\x01\x12\
\x03\x08\x04\x15\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x08\x04\n\n\x0c\
\n\x05\x04\x01\x02\x01\x01\x12\x03\x08\x0b\x10\n\x0c\n\x05\x04\x01\x02\
\x01\x03\x12\x03\x08\x13\x14b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -1,7 +1,10 @@
syntax = "proto3";
message App {
string id = 1;
string workspace_id = 2;
string name = 3;
message User {
string name = 1;
string email = 2;
}
message UserCheck {
string name = 1;
string email = 2;
}