deserialize.rs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. use crate::{derive_cache::TypeCategory, proto_buf::util::*};
  2. use flowy_ast::*;
  3. use proc_macro2::{Span, TokenStream};
  4. pub fn make_de_token_steam(ctxt: &Ctxt, ast: &ASTContainer) -> Option<TokenStream> {
  5. let pb_ty = ast.attrs.pb_struct_type()?;
  6. let struct_ident = &ast.ident;
  7. let build_take_fields = ast
  8. .data
  9. .all_fields()
  10. .filter(|f| !f.attrs.skip_deserializing())
  11. .flat_map(|field| {
  12. if let Some(func) = field.attrs.deserialize_with() {
  13. let member = &field.member;
  14. Some(quote! { o.#member=#struct_ident::#func(pb); })
  15. } else if field.attrs.is_one_of() {
  16. token_stream_for_one_of(ctxt, field)
  17. } else {
  18. token_stream_for_field(ctxt, &field.member, &field.ty, false)
  19. }
  20. });
  21. let de_token_stream: TokenStream = quote! {
  22. impl std::convert::TryFrom<&bytes::Bytes> for #struct_ident {
  23. type Error = ::protobuf::ProtobufError;
  24. fn try_from(bytes: &bytes::Bytes) -> Result<Self, Self::Error> {
  25. let mut pb: crate::protobuf::#pb_ty = ::protobuf::Message::parse_from_bytes(&bytes)?;
  26. #struct_ident::try_from(&mut pb)
  27. }
  28. }
  29. impl std::convert::TryFrom<&mut crate::protobuf::#pb_ty> for #struct_ident {
  30. type Error = ::protobuf::ProtobufError;
  31. fn try_from(pb: &mut crate::protobuf::#pb_ty) -> Result<Self, Self::Error> {
  32. let mut o = Self::default();
  33. #(#build_take_fields)*
  34. Ok(o)
  35. }
  36. }
  37. }
  38. .into();
  39. Some(de_token_stream)
  40. // None
  41. }
  42. fn token_stream_for_one_of(ctxt: &Ctxt, field: &ASTField) -> Option<TokenStream> {
  43. let member = &field.member;
  44. let ident = get_member_ident(ctxt, member)?;
  45. let ty_info = parse_ty(ctxt, &field.ty)?;
  46. let bracketed_ty_info = ty_info.bracket_ty_info.as_ref().as_ref();
  47. let has_func = format_ident!("has_{}", ident.to_string());
  48. // eprintln!("😁{:#?}", ty_info.primitive_ty);
  49. // eprintln!("{:#?}", ty_info.bracket_ty_info);
  50. match ident_category(bracketed_ty_info.unwrap().ident) {
  51. TypeCategory::Enum => {
  52. let get_func = format_ident!("get_{}", ident.to_string());
  53. let ty = ty_info.ty;
  54. Some(quote! {
  55. if pb.#has_func() {
  56. let enum_de_from_pb = #ty::try_from(&pb.#get_func()).unwrap();
  57. o.#member = Some(enum_de_from_pb);
  58. }
  59. })
  60. },
  61. TypeCategory::Primitive => {
  62. let get_func = format_ident!("get_{}", ident.to_string());
  63. Some(quote! {
  64. if pb.#has_func() {
  65. o.#member=Some(pb.#get_func());
  66. }
  67. })
  68. },
  69. TypeCategory::Str => {
  70. let take_func = format_ident!("take_{}", ident.to_string());
  71. Some(quote! {
  72. if pb.#has_func() {
  73. o.#member=Some(pb.#take_func());
  74. }
  75. })
  76. },
  77. TypeCategory::Array => {
  78. let take_func = format_ident!("take_{}", ident.to_string());
  79. Some(quote! {
  80. if pb.#has_func() {
  81. o.#member=Some(pb.#take_func());
  82. }
  83. })
  84. },
  85. _ => {
  86. let take_func = format_ident!("take_{}", ident.to_string());
  87. let ty = bracketed_ty_info.unwrap().ty;
  88. Some(quote! {
  89. if pb.#has_func() {
  90. let val = #ty::try_from(&mut pb.#take_func()).unwrap();
  91. o.#member=Some(val);
  92. }
  93. })
  94. },
  95. }
  96. }
  97. fn token_stream_for_field(
  98. ctxt: &Ctxt,
  99. member: &syn::Member,
  100. ty: &syn::Type,
  101. is_option: bool,
  102. ) -> Option<TokenStream> {
  103. let ident = get_member_ident(ctxt, member)?;
  104. let ty_info = parse_ty(ctxt, ty)?;
  105. match ident_category(ty_info.ident) {
  106. TypeCategory::Array => {
  107. assert_bracket_ty_is_some(ctxt, &ty_info);
  108. token_stream_for_vec(ctxt, &member, &ty_info.bracket_ty_info.unwrap())
  109. },
  110. TypeCategory::Map => {
  111. assert_bracket_ty_is_some(ctxt, &ty_info);
  112. token_stream_for_map(ctxt, &member, &ty_info.bracket_ty_info.unwrap())
  113. },
  114. TypeCategory::Protobuf => {
  115. // if the type wrapped by SingularPtrField, should call take first
  116. let take = syn::Ident::new("take", Span::call_site());
  117. // inner_type_ty would be the type of the field. (e.g value of AnyData)
  118. let ty = ty_info.ty;
  119. Some(quote! {
  120. let some_value = pb.#member.#take();
  121. if some_value.is_some() {
  122. let struct_de_from_pb = #ty::try_from(&mut some_value.unwrap()).unwrap();
  123. o.#member = struct_de_from_pb;
  124. }
  125. })
  126. },
  127. TypeCategory::Enum => {
  128. let ty = ty_info.ty;
  129. Some(quote! {
  130. let enum_de_from_pb = #ty::try_from(&pb.#member).unwrap();
  131. o.#member = enum_de_from_pb;
  132. })
  133. },
  134. TypeCategory::Str => {
  135. let take_ident =
  136. syn::Ident::new(&format!("take_{}", ident.to_string()), Span::call_site());
  137. if is_option {
  138. Some(quote! {
  139. if pb.#member.is_empty() {
  140. o.#member = None;
  141. } else {
  142. o.#member = Some(pb.#take_ident());
  143. }
  144. })
  145. } else {
  146. Some(quote! {
  147. o.#member = pb.#take_ident();
  148. })
  149. }
  150. },
  151. TypeCategory::Opt => {
  152. token_stream_for_field(ctxt, member, ty_info.bracket_ty_info.unwrap().ty, true)
  153. },
  154. TypeCategory::Primitive | TypeCategory::Bytes => {
  155. // eprintln!("😄 #{:?}", &field.name().unwrap());
  156. if is_option {
  157. Some(quote! { o.#member = Some(pb.#member.clone()); })
  158. } else {
  159. Some(quote! { o.#member = pb.#member.clone(); })
  160. }
  161. },
  162. }
  163. }
  164. fn token_stream_for_vec(
  165. ctxt: &Ctxt,
  166. member: &syn::Member,
  167. bracketed_type: &TyInfo,
  168. ) -> Option<TokenStream> {
  169. let ident = get_member_ident(ctxt, member)?;
  170. match ident_category(bracketed_type.ident) {
  171. TypeCategory::Protobuf => {
  172. let ty = bracketed_type.ty;
  173. // Deserialize from pb struct of type vec, should call take_xx(), get the
  174. // repeated_field and then calling the into_iter。
  175. let take_ident = format_ident!("take_{}", ident.to_string());
  176. Some(quote! {
  177. o.#member = pb.#take_ident()
  178. .into_iter()
  179. .map(|mut m| #ty::try_from(&mut m).unwrap())
  180. .collect();
  181. })
  182. },
  183. TypeCategory::Bytes => {
  184. // Vec<u8>
  185. Some(quote! {
  186. o.#member = pb.#member.clone();
  187. })
  188. },
  189. _ => {
  190. // String
  191. let take_ident = format_ident!("take_{}", ident.to_string());
  192. Some(quote! {
  193. o.#member = pb.#take_ident().into_vec();
  194. })
  195. },
  196. }
  197. }
  198. fn token_stream_for_map(
  199. ctxt: &Ctxt,
  200. member: &syn::Member,
  201. bracketed_type: &TyInfo,
  202. ) -> Option<TokenStream> {
  203. let ident = get_member_ident(ctxt, member)?;
  204. let take_ident = format_ident!("take_{}", ident.to_string());
  205. let ty = bracketed_type.ty;
  206. match ident_category(bracketed_type.ident) {
  207. TypeCategory::Protobuf => Some(quote! {
  208. let mut m: std::collections::HashMap<String, #ty> = std::collections::HashMap::new();
  209. pb.#take_ident().into_iter().for_each(|(k,mut v)| {
  210. m.insert(k.clone(), #ty::try_from(&mut v).unwrap());
  211. });
  212. o.#member = m;
  213. }),
  214. _ => Some(quote! {
  215. let mut m: std::collections::HashMap<String, #ty> = std::collections::HashMap::new();
  216. pb.#take_ident().into_iter().for_each(|(k,mut v)| {
  217. m.insert(k.clone(), v);
  218. });
  219. o.#member = m;
  220. }),
  221. }
  222. }