123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- #![allow(clippy::while_let_on_iterator)]
- use crate::proto_buf::util::{get_member_ident, ident_category, TypeCategory};
- use flowy_ast::*;
- use proc_macro2::TokenStream;
- pub fn make_se_token_stream(ast_result: &ASTResult, ast: &ASTContainer) -> Option<TokenStream> {
- let pb_ty = ast.pb_attrs.pb_struct_type()?;
- let struct_ident = &ast.ident;
- let build_set_pb_fields = ast
- .data
- .all_fields()
- .filter(|f| !f.pb_attrs.skip_pb_serializing())
- .flat_map(|field| se_token_stream_for_field(ast_result, field, false));
- let se_token_stream: TokenStream = quote! {
- impl std::convert::TryInto<bytes::Bytes> for #struct_ident {
- type Error = ::protobuf::ProtobufError;
- fn try_into(self) -> Result<bytes::Bytes, Self::Error> {
- use protobuf::Message;
- let pb: crate::protobuf::#pb_ty = self.into();
- let bytes = pb.write_to_bytes()?;
- Ok(bytes::Bytes::from(bytes))
- }
- }
- impl std::convert::From<#struct_ident> for crate::protobuf::#pb_ty {
- fn from(mut o: #struct_ident) -> crate::protobuf::#pb_ty {
- let mut pb = crate::protobuf::#pb_ty::new();
- #(#build_set_pb_fields)*
- pb
- }
- }
- };
- Some(se_token_stream)
- }
- fn se_token_stream_for_field(
- ast_result: &ASTResult,
- field: &ASTField,
- _take: bool,
- ) -> Option<TokenStream> {
- if let Some(func) = &field.pb_attrs.serialize_pb_with() {
- let member = &field.member;
- Some(quote! { pb.#member=o.#func(); })
- } else if field.pb_attrs.is_one_of() {
- token_stream_for_one_of(ast_result, field)
- } else {
- gen_token_stream(ast_result, &field.member, field.ty, false)
- }
- }
- fn token_stream_for_one_of(ast_result: &ASTResult, field: &ASTField) -> Option<TokenStream> {
- let member = &field.member;
- let ident = get_member_ident(ast_result, member)?;
- let ty_info = match parse_ty(ast_result, field.ty) {
- Ok(ty_info) => ty_info,
- Err(e) => {
- eprintln!(
- "token_stream_for_one_of failed: {:?} with error: {}",
- member, e
- );
- panic!();
- },
- }?;
- let bracketed_ty_info = ty_info.bracket_ty_info.as_ref().as_ref();
- let set_func = format_ident!("set_{}", ident.to_string());
- match ident_category(bracketed_ty_info.unwrap().ident) {
- TypeCategory::Protobuf => Some(quote! {
- match o.#member {
- Some(s) => { pb.#set_func(s.into()) }
- None => {}
- }
- }),
- TypeCategory::Enum => Some(quote! {
- match o.#member {
- Some(s) => { pb.#set_func(s.into()) }
- None => {}
- }
- }),
- _ => Some(quote! {
- match o.#member {
- Some(ref s) => { pb.#set_func(s.clone()) }
- None => {}
- }
- }),
- }
- }
- fn gen_token_stream(
- ast_result: &ASTResult,
- member: &syn::Member,
- ty: &syn::Type,
- is_option: bool,
- ) -> Option<TokenStream> {
- let ty_info = match parse_ty(ast_result, ty) {
- Ok(ty_info) => ty_info,
- Err(e) => {
- eprintln!("gen_token_stream failed: {:?} with error: {}", member, e);
- panic!();
- },
- }?;
- match ident_category(ty_info.ident) {
- TypeCategory::Array => {
- token_stream_for_vec(ast_result, member, ty_info.bracket_ty_info.unwrap().ty)
- },
- TypeCategory::Map => {
- token_stream_for_map(ast_result, member, ty_info.bracket_ty_info.unwrap().ty)
- },
- TypeCategory::Str => {
- if is_option {
- Some(quote! {
- match o.#member {
- Some(ref s) => { pb.#member = s.to_string().clone(); }
- None => { pb.#member = String::new(); }
- }
- })
- } else {
- Some(quote! { pb.#member = o.#member.clone(); })
- }
- },
- TypeCategory::Protobuf => {
- Some(quote! { pb.#member = ::protobuf::SingularPtrField::some(o.#member.into()); })
- },
- TypeCategory::Opt => gen_token_stream(
- ast_result,
- 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 = o.#member.into();
- })
- },
- _ => Some(quote! { pb.#member = o.#member; }),
- }
- }
- // e.g. pub cells: Vec<CellData>, the member will be cells, ty would be Vec
- fn token_stream_for_vec(
- ast_result: &ASTResult,
- member: &syn::Member,
- ty: &syn::Type,
- ) -> Option<TokenStream> {
- let ty_info = match parse_ty(ast_result, ty) {
- Ok(ty_info) => ty_info,
- Err(e) => {
- eprintln!(
- "token_stream_for_vec failed: {:?} with error: {}",
- member, e
- );
- panic!();
- },
- }?;
- match ident_category(ty_info.ident) {
- TypeCategory::Protobuf => Some(quote! {
- pb.#member = ::protobuf::RepeatedField::from_vec(
- o.#member
- .into_iter()
- .map(|m| m.into())
- .collect());
- }),
- TypeCategory::Bytes => Some(quote! { pb.#member = o.#member.clone(); }),
- _ => Some(quote! {
- pb.#member = ::protobuf::RepeatedField::from_vec(o.#member.clone());
- }),
- }
- }
- // e.g. pub cells: HashMap<xx, xx>
- fn token_stream_for_map(
- ast_result: &ASTResult,
- member: &syn::Member,
- ty: &syn::Type,
- ) -> Option<TokenStream> {
- // The key of the hashmap must be string
- let ty_info = match parse_ty(ast_result, ty) {
- Ok(ty_info) => ty_info,
- Err(e) => {
- eprintln!(
- "token_stream_for_map failed: {:?} with error: {}",
- member, e
- );
- panic!();
- },
- }?;
- let value_ty = ty_info.ty;
- match ident_category(ty_info.ident) {
- TypeCategory::Protobuf => Some(quote! {
- let mut m: std::collections::HashMap<String, crate::protobuf::#value_ty> = std::collections::HashMap::new();
- o.#member.into_iter().for_each(|(k,v)| {
- m.insert(k.clone(), v.into());
- });
- pb.#member = m;
- }),
- _ => Some(quote! {
- let mut m: std::collections::HashMap<String, #value_ty> = std::collections::HashMap::new();
- o.#member.iter().for_each(|(k,v)| {
- m.insert(k.clone(), v.clone());
- });
- pb.#member = m;
- }),
- }
- }
|