serialize.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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.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(ctxt: &Ctxt, field: &ASTField, _take: bool) -> Option<TokenStream> {
  34. if let Some(func) = &field.attrs.serialize_with() {
  35. let member = &field.member;
  36. Some(quote! { pb.#member=o.#func(); })
  37. } else if field.attrs.is_one_of() {
  38. token_stream_for_one_of(ctxt, field)
  39. } else {
  40. gen_token_stream(ctxt, &field.member, field.ty, false)
  41. }
  42. }
  43. fn token_stream_for_one_of(ctxt: &Ctxt, field: &ASTField) -> Option<TokenStream> {
  44. let member = &field.member;
  45. let ident = get_member_ident(ctxt, member)?;
  46. let ty_info = match parse_ty(ctxt, field.ty) {
  47. Ok(ty_info) => ty_info,
  48. Err(e) => {
  49. eprintln!("token_stream_for_one_of failed: {:?} with error: {}", member, e);
  50. panic!();
  51. }
  52. }?;
  53. let bracketed_ty_info = ty_info.bracket_ty_info.as_ref().as_ref();
  54. let set_func = format_ident!("set_{}", ident.to_string());
  55. match ident_category(bracketed_ty_info.unwrap().ident) {
  56. TypeCategory::Protobuf => Some(quote! {
  57. match o.#member {
  58. Some(s) => { pb.#set_func(s.into()) }
  59. None => {}
  60. }
  61. }),
  62. TypeCategory::Enum => Some(quote! {
  63. match o.#member {
  64. Some(s) => { pb.#set_func(s.into()) }
  65. None => {}
  66. }
  67. }),
  68. _ => Some(quote! {
  69. match o.#member {
  70. Some(ref s) => { pb.#set_func(s.clone()) }
  71. None => {}
  72. }
  73. }),
  74. }
  75. }
  76. fn gen_token_stream(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type, is_option: bool) -> Option<TokenStream> {
  77. let ty_info = match parse_ty(ctxt, ty) {
  78. Ok(ty_info) => ty_info,
  79. Err(e) => {
  80. eprintln!("gen_token_stream failed: {:?} with error: {}", member, e);
  81. panic!();
  82. }
  83. }?;
  84. match ident_category(ty_info.ident) {
  85. TypeCategory::Array => token_stream_for_vec(ctxt, member, ty_info.bracket_ty_info.unwrap().ty),
  86. TypeCategory::Map => token_stream_for_map(ctxt, member, ty_info.bracket_ty_info.unwrap().ty),
  87. TypeCategory::Str => {
  88. if is_option {
  89. Some(quote! {
  90. match o.#member {
  91. Some(ref s) => { pb.#member = s.to_string().clone(); }
  92. None => { pb.#member = String::new(); }
  93. }
  94. })
  95. } else {
  96. Some(quote! { pb.#member = o.#member.clone(); })
  97. }
  98. }
  99. TypeCategory::Protobuf => Some(quote! { pb.#member = ::protobuf::SingularPtrField::some(o.#member.into()); }),
  100. TypeCategory::Opt => gen_token_stream(ctxt, member, ty_info.bracket_ty_info.unwrap().ty, true),
  101. TypeCategory::Enum => {
  102. // let pb_enum_ident = format_ident!("{}", ty_info.ident.to_string());
  103. // Some(quote! {
  104. // flowy_protobuf::#pb_enum_ident::from_i32(self.#member.value()).unwrap();
  105. // })
  106. Some(quote! {
  107. pb.#member = o.#member.into();
  108. })
  109. }
  110. _ => Some(quote! { pb.#member = o.#member; }),
  111. }
  112. }
  113. // e.g. pub cells: Vec<CellData>, the member will be cells, ty would be Vec
  114. fn token_stream_for_vec(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Option<TokenStream> {
  115. let ty_info = match parse_ty(ctxt, ty) {
  116. Ok(ty_info) => ty_info,
  117. Err(e) => {
  118. eprintln!("token_stream_for_vec failed: {:?} with error: {}", member, e);
  119. panic!();
  120. }
  121. }?;
  122. match ident_category(ty_info.ident) {
  123. TypeCategory::Protobuf => Some(quote! {
  124. pb.#member = ::protobuf::RepeatedField::from_vec(
  125. o.#member
  126. .into_iter()
  127. .map(|m| m.into())
  128. .collect());
  129. }),
  130. TypeCategory::Bytes => Some(quote! { pb.#member = o.#member.clone(); }),
  131. _ => Some(quote! {
  132. pb.#member = ::protobuf::RepeatedField::from_vec(o.#member.clone());
  133. }),
  134. }
  135. }
  136. // e.g. pub cells: HashMap<xx, xx>
  137. fn token_stream_for_map(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Option<TokenStream> {
  138. // The key of the hashmap must be string
  139. let ty_info = match parse_ty(ctxt, ty) {
  140. Ok(ty_info) => ty_info,
  141. Err(e) => {
  142. eprintln!("token_stream_for_map failed: {:?} with error: {}", member, e);
  143. panic!();
  144. }
  145. }?;
  146. let value_ty = ty_info.ty;
  147. match ident_category(ty_info.ident) {
  148. TypeCategory::Protobuf => Some(quote! {
  149. let mut m: std::collections::HashMap<String, crate::protobuf::#value_ty> = std::collections::HashMap::new();
  150. o.#member.into_iter().for_each(|(k,v)| {
  151. m.insert(k.clone(), v.into());
  152. });
  153. pb.#member = m;
  154. }),
  155. _ => Some(quote! {
  156. let mut m: std::collections::HashMap<String, #value_ty> = std::collections::HashMap::new();
  157. o.#member.iter().for_each(|(k,v)| {
  158. m.insert(k.clone(), v.clone());
  159. });
  160. pb.#member = m;
  161. }),
  162. }
  163. }