serialize.rs 6.4 KB

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