serialize.rs 6.6 KB

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