serialize.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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(ast_result: &ASTResult, ast: &ASTContainer) -> Option<TokenStream> {
  6. let pb_ty = ast.pb_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.pb_attrs.skip_pb_serializing())
  12. .flat_map(|field| se_token_stream_for_field(ast_result, 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.into();
  19. let bytes = pb.write_to_bytes()?;
  20. Ok(bytes::Bytes::from(bytes))
  21. }
  22. }
  23. impl std::convert::From<#struct_ident> for crate::protobuf::#pb_ty {
  24. fn from(mut o: #struct_ident) -> crate::protobuf::#pb_ty {
  25. let mut pb = crate::protobuf::#pb_ty::new();
  26. #(#build_set_pb_fields)*
  27. pb
  28. }
  29. }
  30. };
  31. Some(se_token_stream)
  32. }
  33. fn se_token_stream_for_field(
  34. ast_result: &ASTResult,
  35. field: &ASTField,
  36. _take: bool,
  37. ) -> Option<TokenStream> {
  38. if let Some(func) = &field.pb_attrs.serialize_pb_with() {
  39. let member = &field.member;
  40. Some(quote! { pb.#member=o.#func(); })
  41. } else if field.pb_attrs.is_one_of() {
  42. token_stream_for_one_of(ast_result, field)
  43. } else {
  44. gen_token_stream(ast_result, &field.member, field.ty, false)
  45. }
  46. }
  47. fn token_stream_for_one_of(ast_result: &ASTResult, field: &ASTField) -> Option<TokenStream> {
  48. let member = &field.member;
  49. let ident = get_member_ident(ast_result, member)?;
  50. let ty_info = match parse_ty(ast_result, field.ty) {
  51. Ok(ty_info) => ty_info,
  52. Err(e) => {
  53. eprintln!(
  54. "token_stream_for_one_of failed: {:?} with error: {}",
  55. member, e
  56. );
  57. panic!();
  58. },
  59. }?;
  60. let bracketed_ty_info = ty_info.bracket_ty_info.as_ref().as_ref();
  61. let set_func = format_ident!("set_{}", ident.to_string());
  62. match ident_category(bracketed_ty_info.unwrap().ident) {
  63. TypeCategory::Protobuf => Some(quote! {
  64. match o.#member {
  65. Some(s) => { pb.#set_func(s.into()) }
  66. None => {}
  67. }
  68. }),
  69. TypeCategory::Enum => Some(quote! {
  70. match o.#member {
  71. Some(s) => { pb.#set_func(s.into()) }
  72. None => {}
  73. }
  74. }),
  75. _ => Some(quote! {
  76. match o.#member {
  77. Some(ref s) => { pb.#set_func(s.clone()) }
  78. None => {}
  79. }
  80. }),
  81. }
  82. }
  83. fn gen_token_stream(
  84. ast_result: &ASTResult,
  85. member: &syn::Member,
  86. ty: &syn::Type,
  87. is_option: bool,
  88. ) -> Option<TokenStream> {
  89. let ty_info = match parse_ty(ast_result, ty) {
  90. Ok(ty_info) => ty_info,
  91. Err(e) => {
  92. eprintln!("gen_token_stream failed: {:?} with error: {}", member, e);
  93. panic!();
  94. },
  95. }?;
  96. match ident_category(ty_info.ident) {
  97. TypeCategory::Array => {
  98. token_stream_for_vec(ast_result, member, ty_info.bracket_ty_info.unwrap().ty)
  99. },
  100. TypeCategory::Map => {
  101. token_stream_for_map(ast_result, member, ty_info.bracket_ty_info.unwrap().ty)
  102. },
  103. TypeCategory::Str => {
  104. if is_option {
  105. Some(quote! {
  106. match o.#member {
  107. Some(ref s) => { pb.#member = s.to_string().clone(); }
  108. None => { pb.#member = String::new(); }
  109. }
  110. })
  111. } else {
  112. Some(quote! { pb.#member = o.#member.clone(); })
  113. }
  114. },
  115. TypeCategory::Protobuf => {
  116. Some(quote! { pb.#member = ::protobuf::SingularPtrField::some(o.#member.into()); })
  117. },
  118. TypeCategory::Opt => gen_token_stream(
  119. ast_result,
  120. member,
  121. ty_info.bracket_ty_info.unwrap().ty,
  122. true,
  123. ),
  124. TypeCategory::Enum => {
  125. // let pb_enum_ident = format_ident!("{}", ty_info.ident.to_string());
  126. // Some(quote! {
  127. // flowy_protobuf::#pb_enum_ident::from_i32(self.#member.value()).unwrap();
  128. // })
  129. Some(quote! {
  130. pb.#member = o.#member.into();
  131. })
  132. },
  133. _ => Some(quote! { pb.#member = o.#member; }),
  134. }
  135. }
  136. // e.g. pub cells: Vec<CellData>, the member will be cells, ty would be Vec
  137. fn token_stream_for_vec(
  138. ast_result: &ASTResult,
  139. member: &syn::Member,
  140. ty: &syn::Type,
  141. ) -> Option<TokenStream> {
  142. let ty_info = match parse_ty(ast_result, ty) {
  143. Ok(ty_info) => ty_info,
  144. Err(e) => {
  145. eprintln!(
  146. "token_stream_for_vec failed: {:?} with error: {}",
  147. member, e
  148. );
  149. panic!();
  150. },
  151. }?;
  152. match ident_category(ty_info.ident) {
  153. TypeCategory::Protobuf => Some(quote! {
  154. pb.#member = ::protobuf::RepeatedField::from_vec(
  155. o.#member
  156. .into_iter()
  157. .map(|m| m.into())
  158. .collect());
  159. }),
  160. TypeCategory::Bytes => Some(quote! { pb.#member = o.#member.clone(); }),
  161. _ => Some(quote! {
  162. pb.#member = ::protobuf::RepeatedField::from_vec(o.#member.clone());
  163. }),
  164. }
  165. }
  166. // e.g. pub cells: HashMap<xx, xx>
  167. fn token_stream_for_map(
  168. ast_result: &ASTResult,
  169. member: &syn::Member,
  170. ty: &syn::Type,
  171. ) -> Option<TokenStream> {
  172. // The key of the hashmap must be string
  173. let ty_info = match parse_ty(ast_result, ty) {
  174. Ok(ty_info) => ty_info,
  175. Err(e) => {
  176. eprintln!(
  177. "token_stream_for_map failed: {:?} with error: {}",
  178. member, e
  179. );
  180. panic!();
  181. },
  182. }?;
  183. let value_ty = ty_info.ty;
  184. match ident_category(ty_info.ident) {
  185. TypeCategory::Protobuf => Some(quote! {
  186. let mut m: std::collections::HashMap<String, crate::protobuf::#value_ty> = std::collections::HashMap::new();
  187. o.#member.into_iter().for_each(|(k,v)| {
  188. m.insert(k.clone(), v.into());
  189. });
  190. pb.#member = m;
  191. }),
  192. _ => Some(quote! {
  193. let mut m: std::collections::HashMap<String, #value_ty> = std::collections::HashMap::new();
  194. o.#member.iter().for_each(|(k,v)| {
  195. m.insert(k.clone(), v.clone());
  196. });
  197. pb.#member = m;
  198. }),
  199. }
  200. }