serialize.rs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. use crate::{derive_cache::TypeCategory, proto_buf::util::ident_category};
  2. use flowy_ast::*;
  3. use proc_macro2::TokenStream;
  4. pub fn make_se_token_stream(ctxt: &Ctxt, ast: &ASTContainer) -> Option<TokenStream> {
  5. let pb_ty = ast.attrs.pb_struct_type()?;
  6. let struct_ident = &ast.ident;
  7. let build_set_pb_fields = ast
  8. .data
  9. .all_fields()
  10. .filter(|f| !f.attrs.skip_serializing())
  11. .flat_map(|field| se_token_stream_for_field(&ctxt, &field, false));
  12. let build_set_fields = ast
  13. .data
  14. .all_fields()
  15. .filter(|f| !f.attrs.skip_serializing())
  16. .flat_map(|field| se_token_stream_for_field(&ctxt, &field, false));
  17. let se_token_stream: TokenStream = quote! {
  18. impl std::convert::TryInto<Vec<u8>> for #struct_ident {
  19. type Error = String;
  20. fn try_into(self) -> Result<Vec<u8>, Self::Error> {
  21. use protobuf::Message;
  22. let pb: crate::protobuf::#pb_ty = self.try_into()?;
  23. let result: ::protobuf::ProtobufResult<Vec<u8>> = pb.write_to_bytes();
  24. match result {
  25. Ok(bytes) => { Ok(bytes) },
  26. Err(e) => { Err(format!("{:?}", e)) }
  27. }
  28. }
  29. }
  30. impl std::convert::TryInto<crate::protobuf::#pb_ty> for #struct_ident {
  31. type Error = String;
  32. fn try_into(self) -> Result<crate::protobuf::#pb_ty, Self::Error> {
  33. let mut pb = crate::protobuf::#pb_ty::new();
  34. #(#build_set_pb_fields)*
  35. Ok(pb)
  36. }
  37. }
  38. }
  39. .into();
  40. Some(se_token_stream)
  41. }
  42. fn se_token_stream_for_field(ctxt: &Ctxt, field: &ASTField, _take: bool) -> Option<TokenStream> {
  43. if let Some(func) = &field.attrs.serialize_with() {
  44. let member = &field.member;
  45. Some(quote! { pb.#member=self.#func(); })
  46. } else if field.attrs.is_one_of() {
  47. let member = &field.member;
  48. match &field.member {
  49. syn::Member::Named(ref ident) => {
  50. let set_func = format_ident!("set_{}", ident.to_string());
  51. Some(quote! {
  52. match self.#member {
  53. Some(ref s) => { pb.#set_func(s.to_protobuf()) }
  54. None => {}
  55. }
  56. })
  57. },
  58. _ => {
  59. ctxt.error_spanned_by(member, format!("Unsupported member, get member ident fail"));
  60. None
  61. },
  62. }
  63. } else {
  64. gen_token_stream(ctxt, &field.member, &field.ty, false)
  65. }
  66. }
  67. fn gen_token_stream(
  68. ctxt: &Ctxt,
  69. member: &syn::Member,
  70. ty: &syn::Type,
  71. is_option: bool,
  72. ) -> Option<TokenStream> {
  73. let ty_info = parse_ty(ctxt, ty)?;
  74. match ident_category(ty_info.ident) {
  75. TypeCategory::Array => token_stream_for_vec(ctxt, &member, &ty_info.ty),
  76. TypeCategory::Map => {
  77. token_stream_for_map(ctxt, &member, &ty_info.bracket_ty_info.unwrap().ty)
  78. },
  79. TypeCategory::Str => {
  80. if is_option {
  81. Some(quote! {
  82. match self.#member {
  83. Some(ref s) => { pb.#member = s.to_string().clone(); }
  84. None => { pb.#member = String::new(); }
  85. }
  86. })
  87. } else {
  88. Some(quote! { pb.#member = self.#member.clone(); })
  89. }
  90. },
  91. TypeCategory::Protobuf => Some(
  92. quote! { pb.#member = ::protobuf::SingularPtrField::some(self.#member.to_protobuf()); },
  93. ),
  94. TypeCategory::Opt => {
  95. gen_token_stream(ctxt, member, ty_info.bracket_ty_info.unwrap().ty, true)
  96. },
  97. TypeCategory::Enum => {
  98. // let pb_enum_ident = format_ident!("{}", ty_info.ident.to_string());
  99. // Some(quote! {
  100. // flowy_protobuf::#pb_enum_ident::from_i32(self.#member.value()).unwrap();
  101. // })
  102. Some(quote! {
  103. pb.#member = self.#member.to_protobuf();
  104. })
  105. },
  106. _ => Some(quote! { pb.#member = self.#member; }),
  107. }
  108. }
  109. // e.g. pub cells: Vec<CellData>, the memeber will be cells, ty would be Vec
  110. fn token_stream_for_vec(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Option<TokenStream> {
  111. let ty_info = parse_ty(ctxt, ty)?;
  112. match ident_category(ty_info.ident) {
  113. TypeCategory::Protobuf => Some(quote! {
  114. pb.#member = ::protobuf::RepeatedField::from_vec(
  115. self.#member
  116. .iter()
  117. .map(|m| m.to_protobuf())
  118. .collect());
  119. }),
  120. TypeCategory::Bytes => Some(quote! { pb.#member = self.#member.clone(); }),
  121. _ => Some(quote! {
  122. pb.#member = ::protobuf::RepeatedField::from_vec(self.#member.clone());
  123. }),
  124. }
  125. }
  126. // e.g. pub cells: HashMap<xx, xx>
  127. fn token_stream_for_map(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Option<TokenStream> {
  128. // The key of the hashmap must be string
  129. let flowy_protobuf = format_ident!("flowy_protobuf");
  130. let ty_info = parse_ty(ctxt, ty)?;
  131. match ident_category(ty_info.ident) {
  132. TypeCategory::Protobuf => {
  133. let value_type = ty_info.ident;
  134. Some(quote! {
  135. let mut m: std::collections::HashMap<String, #flowy_protobuf::#value_type> = std::collections::HashMap::new();
  136. self.#member.iter().for_each(|(k,v)| {
  137. m.insert(k.clone(), v.to_protobuf());
  138. });
  139. pb.#member = m;
  140. })
  141. },
  142. _ => {
  143. let value_type = ty_info.ident;
  144. Some(quote! {
  145. let mut m: std::collections::HashMap<String, #flowy_protobuf::#value_type> = std::collections::HashMap::new();
  146. self.#member.iter().for_each(|(k,v)| {
  147. m.insert(k.clone(), v.clone());
  148. });
  149. pb.#member = m;
  150. })
  151. },
  152. }
  153. }