1 use protobuf::descriptor::*;
2 use protobuf::descriptorx::*;
3 
4 use super::code_writer::*;
5 use super::customize::customize_from_rustproto_for_message;
6 use super::customize::Customize;
7 use super::enums::*;
8 use super::field::*;
9 use super::rust_types_values::*;
10 use inside::protobuf_crate_path;
11 use oneof::OneofGen;
12 use oneof::OneofVariantGen;
13 use serde;
14 
15 /// Message info for codegen
16 pub struct MessageGen<'a> {
17     pub(crate) message: &'a MessageWithScope<'a>,
18     pub(crate) root_scope: &'a RootScope<'a>,
19     type_name: String,
20     pub fields: Vec<FieldGen<'a>>,
21     pub lite_runtime: bool,
22     customize: Customize,
23 }
24 
25 impl<'a> MessageGen<'a> {
new( message: &'a MessageWithScope<'a>, root_scope: &'a RootScope<'a>, customize: &Customize, ) -> MessageGen<'a>26     pub fn new(
27         message: &'a MessageWithScope<'a>,
28         root_scope: &'a RootScope<'a>,
29         customize: &Customize,
30     ) -> MessageGen<'a> {
31         let mut customize = customize.clone();
32         customize.update_with(&customize_from_rustproto_for_message(
33             message.message.get_options(),
34         ));
35 
36         let fields: Vec<_> = message
37             .fields()
38             .into_iter()
39             .map(|field| FieldGen::parse(field, root_scope, &customize))
40             .collect();
41         let lite_runtime = customize.lite_runtime.unwrap_or_else(|| {
42             message
43                 .get_file_descriptor()
44                 .get_options()
45                 .get_optimize_for()
46                 == FileOptions_OptimizeMode::LITE_RUNTIME
47         });
48         MessageGen {
49             message: message,
50             root_scope: root_scope,
51             type_name: message.rust_name(),
52             fields: fields,
53             lite_runtime,
54             customize,
55         }
56     }
57 
expose_oneof(&self) -> bool58     fn expose_oneof(&self) -> bool {
59         self.customize.expose_oneof.unwrap_or(true)
60     }
61 
oneofs(&'a self) -> Vec<OneofGen<'a>>62     fn oneofs(&'a self) -> Vec<OneofGen<'a>> {
63         self.message
64             .oneofs()
65             .into_iter()
66             .map(|oneof| OneofGen::parse(self, oneof, &self.customize))
67             .collect()
68     }
69 
required_fields(&'a self) -> Vec<&'a FieldGen>70     fn required_fields(&'a self) -> Vec<&'a FieldGen> {
71         self.fields
72             .iter()
73             .filter(|f| match f.kind {
74                 FieldKind::Singular(ref singular) => singular.flag.is_required(),
75                 _ => false,
76             })
77             .collect()
78     }
79 
message_fields(&'a self) -> Vec<&'a FieldGen>80     fn message_fields(&'a self) -> Vec<&'a FieldGen> {
81         self.fields
82             .iter()
83             .filter(|f| f.proto_type == FieldDescriptorProto_Type::TYPE_MESSAGE)
84             .collect()
85     }
86 
fields_except_oneof(&'a self) -> Vec<&'a FieldGen>87     fn fields_except_oneof(&'a self) -> Vec<&'a FieldGen> {
88         self.fields.iter().filter(|f| !f.is_oneof()).collect()
89     }
90 
fields_except_group(&'a self) -> Vec<&'a FieldGen>91     fn fields_except_group(&'a self) -> Vec<&'a FieldGen> {
92         self.fields
93             .iter()
94             .filter(|f| f.proto_type != FieldDescriptorProto_Type::TYPE_GROUP)
95             .collect()
96     }
97 
fields_except_oneof_and_group(&'a self) -> Vec<&'a FieldGen>98     fn fields_except_oneof_and_group(&'a self) -> Vec<&'a FieldGen> {
99         self.fields
100             .iter()
101             .filter(|f| !f.is_oneof() && f.proto_type != FieldDescriptorProto_Type::TYPE_GROUP)
102             .collect()
103     }
104 
write_match_each_oneof_variant<F>(&self, w: &mut CodeWriter, cb: F) where F: Fn(&mut CodeWriter, &OneofVariantGen, &str, &RustType),105     fn write_match_each_oneof_variant<F>(&self, w: &mut CodeWriter, cb: F)
106     where
107         F: Fn(&mut CodeWriter, &OneofVariantGen, &str, &RustType),
108     {
109         for oneof in self.oneofs() {
110             w.if_let_stmt(
111                 "::std::option::Option::Some(ref v)",
112                 &format!("self.{}", oneof.name())[..],
113                 |w| {
114                     w.match_block("v", |w| {
115                         for variant in oneof.variants_except_group() {
116                             let ref field = variant.field;
117                             let (refv, vtype) = if !field.elem_type_is_copy() {
118                                 ("ref v", field.elem().rust_storage_type().ref_type())
119                             } else {
120                                 ("v", field.elem().rust_storage_type())
121                             };
122                             w.case_block(format!("&{}({})", variant.path(), refv), |w| {
123                                 cb(w, &variant, "v", &vtype);
124                             });
125                         }
126                     });
127                 },
128             );
129         }
130     }
131 
write_write_to_with_cached_sizes(&self, w: &mut CodeWriter)132     fn write_write_to_with_cached_sizes(&self, w: &mut CodeWriter) {
133         let sig = format!(
134             "write_to_with_cached_sizes(&self, os: &mut {}::CodedOutputStream<'_>) -> {}::ProtobufResult<()>",
135             protobuf_crate_path(&self.customize),
136             protobuf_crate_path(&self.customize),
137         );
138         w.def_fn(&sig, |w| {
139             // To have access to its methods but not polute the name space.
140             for f in self.fields_except_oneof_and_group() {
141                 f.write_message_write_field(w);
142             }
143             self.write_match_each_oneof_variant(w, |w, variant, v, v_type| {
144                 variant.field.write_write_element(w, "os", v, v_type);
145             });
146             w.write_line("os.write_unknown_fields(self.get_unknown_fields())?;");
147             w.write_line("::std::result::Result::Ok(())");
148         });
149     }
150 
write_get_cached_size(&self, w: &mut CodeWriter)151     fn write_get_cached_size(&self, w: &mut CodeWriter) {
152         w.def_fn("get_cached_size(&self) -> u32", |w| {
153             w.write_line("self.cached_size.get()");
154         });
155     }
156 
write_default_instance(&self, w: &mut CodeWriter)157     fn write_default_instance(&self, w: &mut CodeWriter) {
158         w.def_fn(
159             &format!("default_instance() -> &'static {}", self.type_name),
160             |w| {
161                 w.lazy_static_decl_get_simple(
162                     "instance",
163                     &self.type_name,
164                     &format!("{}::new", self.type_name),
165                 );
166             },
167         );
168     }
169 
write_compute_size(&self, w: &mut CodeWriter)170     fn write_compute_size(&self, w: &mut CodeWriter) {
171         // Append sizes of messages in the tree to the specified vector.
172         // First appended element is size of self, and then nested message sizes.
173         // in serialization order are appended recursively.");
174         w.comment("Compute sizes of nested messages");
175         // there are unused variables in oneof
176         w.allow(&["unused_variables"]);
177         w.def_fn("compute_size(&self) -> u32", |w| {
178             // To have access to its methods but not polute the name space.
179             w.write_line("let mut my_size = 0;");
180             for field in self.fields_except_oneof_and_group() {
181                 field.write_message_compute_field_size("my_size", w);
182             }
183             self.write_match_each_oneof_variant(w, |w, variant, v, vtype| {
184                 variant.field.write_element_size(w, v, vtype, "my_size");
185             });
186             w.write_line(&format!(
187                 "my_size += {}::rt::unknown_fields_size(self.get_unknown_fields());",
188                 protobuf_crate_path(&self.customize)
189             ));
190             w.write_line("self.cached_size.set(my_size);");
191             w.write_line("my_size");
192         });
193     }
194 
write_field_accessors(&self, w: &mut CodeWriter)195     fn write_field_accessors(&self, w: &mut CodeWriter) {
196         for f in self.fields_except_group() {
197             w.write_line("");
198             let reconstruct_def = f.reconstruct_def();
199             w.comment(&(reconstruct_def + ";"));
200             w.write_line("");
201             f.write_message_single_field_accessors(w);
202         }
203     }
204 
write_impl_self(&self, w: &mut CodeWriter)205     fn write_impl_self(&self, w: &mut CodeWriter) {
206         w.impl_self_block(&self.type_name, |w| {
207             // TODO: new should probably be a part of Message trait
208             w.pub_fn(&format!("new() -> {}", self.type_name), |w| {
209                 w.write_line("::std::default::Default::default()");
210             });
211 
212             self.write_field_accessors(w);
213         });
214     }
215 
write_unknown_fields(&self, w: &mut CodeWriter)216     fn write_unknown_fields(&self, w: &mut CodeWriter) {
217         w.def_fn(
218             "get_unknown_fields(&self) -> &::protobuf::UnknownFields",
219             |w| {
220                 w.write_line("&self.unknown_fields");
221             },
222         );
223         w.write_line("");
224         w.def_fn(
225             "mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields",
226             |w| {
227                 w.write_line("&mut self.unknown_fields");
228             },
229         );
230     }
231 
write_merge_from(&self, w: &mut CodeWriter)232     fn write_merge_from(&self, w: &mut CodeWriter) {
233         let sig = format!(
234             "merge_from(&mut self, is: &mut {}::CodedInputStream<'_>) -> {}::ProtobufResult<()>",
235             protobuf_crate_path(&self.customize),
236             protobuf_crate_path(&self.customize),
237         );
238         w.def_fn(&sig, |w| {
239             w.while_block("!is.eof()?", |w| {
240                 w.write_line(&format!("let (field_number, wire_type) = is.read_tag_unpack()?;"));
241                 w.match_block("field_number", |w| {
242                     for f in &self.fields_except_group() {
243                         let number = f.proto_field.number();
244                         w.case_block(number.to_string(), |w| {
245                             f.write_merge_from_field("wire_type", w);
246                         });
247                     }
248                     w.case_block("_", |w| {
249                         w.write_line(&format!("{}::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;", protobuf_crate_path(&self.customize)));
250                     });
251                 });
252             });
253             w.write_line("::std::result::Result::Ok(())");
254         });
255     }
256 
write_descriptor_field(&self, fields_var: &str, field: &FieldGen, w: &mut CodeWriter)257     fn write_descriptor_field(&self, fields_var: &str, field: &FieldGen, w: &mut CodeWriter) {
258         let accessor_fn = field.accessor_fn();
259         w.write_line(&format!(
260             "{}.push(::protobuf::reflect::accessor::{}(",
261             fields_var,
262             accessor_fn.sig()
263         ));
264         w.indented(|w| {
265             w.write_line(&format!("\"{}\",", field.proto_field.name()));
266             match accessor_fn.style {
267                 AccessorStyle::Lambda => {
268                     w.write_line(&format!(
269                         "|m: &{}| {{ &m.{} }},",
270                         self.type_name, field.rust_name
271                     ));
272                     w.write_line(&format!(
273                         "|m: &mut {}| {{ &mut m.{} }},",
274                         self.type_name, field.rust_name
275                     ));
276                 }
277                 AccessorStyle::HasGet => {
278                     w.write_line(&format!("{}::has_{},", self.type_name, field.rust_name));
279                     w.write_line(&format!("{}::get_{},", self.type_name, field.rust_name));
280                 }
281             }
282         });
283         w.write_line("));");
284     }
285 
write_descriptor_static(&self, w: &mut CodeWriter)286     fn write_descriptor_static(&self, w: &mut CodeWriter) {
287         w.def_fn(
288             &format!("descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor"),
289             |w| {
290                 w.lazy_static_decl_get(
291                     "descriptor",
292                     "::protobuf::reflect::MessageDescriptor",
293                     |w| {
294                         let fields = self.fields_except_group();
295                         if fields.is_empty() {
296                             w.write_line(&format!("let fields = ::std::vec::Vec::new();"));
297                         } else {
298                             w.write_line(&format!("let mut fields = ::std::vec::Vec::new();"));
299                         }
300                         for field in fields {
301                             self.write_descriptor_field("fields", field, w);
302                         }
303                         w.write_line(&format!(
304                             "::protobuf::reflect::MessageDescriptor::new::<{}>(",
305                             self.type_name
306                         ));
307                         w.indented(|w| {
308                             w.write_line(&format!("\"{}\",", self.type_name));
309                             w.write_line("fields,");
310                             w.write_line("file_descriptor_proto()");
311                         });
312                         w.write_line(")");
313                     },
314                 );
315             },
316         );
317     }
318 
write_is_initialized(&self, w: &mut CodeWriter)319     fn write_is_initialized(&self, w: &mut CodeWriter) {
320         w.def_fn(&format!("is_initialized(&self) -> bool"), |w| {
321             // TODO: use single loop
322 
323             for f in self.required_fields() {
324                 f.write_if_self_field_is_none(w, |w| {
325                     w.write_line("return false;");
326                 });
327             }
328 
329             for f in self.message_fields() {
330                 if let FieldKind::Map(..) = f.kind {
331                     // TODO: check values
332                     continue;
333                 }
334 
335                 // TODO:
336                 // if message is declared in this file and has no message fields,
337                 // we could skip the check here
338                 f.write_for_self_field(w, "v", |w, _t| {
339                     w.if_stmt("!v.is_initialized()", |w| {
340                         w.write_line("return false;");
341                     });
342                 });
343             }
344             w.write_line("true");
345         });
346     }
347 
write_impl_message(&self, w: &mut CodeWriter)348     fn write_impl_message(&self, w: &mut CodeWriter) {
349         w.impl_for_block("::protobuf::Message", &self.type_name, |w| {
350             self.write_is_initialized(w);
351             w.write_line("");
352             self.write_merge_from(w);
353             w.write_line("");
354             self.write_compute_size(w);
355             w.write_line("");
356             self.write_write_to_with_cached_sizes(w);
357             w.write_line("");
358             self.write_get_cached_size(w);
359             w.write_line("");
360             self.write_unknown_fields(w);
361             w.write_line("");
362             w.def_fn("as_any(&self) -> &dyn (::std::any::Any)", |w| {
363                 w.write_line("self as &dyn (::std::any::Any)");
364             });
365             w.def_fn("as_any_mut(&mut self) -> &mut dyn (::std::any::Any)", |w| {
366                 w.write_line("self as &mut dyn (::std::any::Any)");
367             });
368             w.def_fn(
369                 "into_any(self: Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)>",
370                 |w| {
371                     w.write_line("self");
372                 },
373             );
374             w.write_line("");
375             w.def_fn(
376                 "descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor",
377                 |w| {
378                     w.write_line("Self::descriptor_static()");
379                 },
380             );
381             w.write_line("");
382             w.def_fn(&format!("new() -> {}", self.type_name), |w| {
383                 w.write_line(&format!("{}::new()", self.type_name));
384             });
385             if !self.lite_runtime {
386                 w.write_line("");
387                 self.write_descriptor_static(w);
388             }
389             w.write_line("");
390             self.write_default_instance(w);
391         });
392     }
393 
write_impl_value(&self, w: &mut CodeWriter)394     fn write_impl_value(&self, w: &mut CodeWriter) {
395         w.impl_for_block("::protobuf::reflect::ProtobufValue", &self.type_name, |w| {
396             w.def_fn(
397                 "as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef",
398                 |w| w.write_line("::protobuf::reflect::ProtobufValueRef::Message(self)"),
399             )
400         })
401     }
402 
write_impl_show(&self, w: &mut CodeWriter)403     fn write_impl_show(&self, w: &mut CodeWriter) {
404         w.impl_for_block("::std::fmt::Debug", &self.type_name, |w| {
405             w.def_fn(
406                 "fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result",
407                 |w| {
408                     w.write_line("::protobuf::text_format::fmt(self, f)");
409                 },
410             );
411         });
412     }
413 
write_impl_clear(&self, w: &mut CodeWriter)414     fn write_impl_clear(&self, w: &mut CodeWriter) {
415         w.impl_for_block("::protobuf::Clear", &self.type_name, |w| {
416             w.def_fn("clear(&mut self)", |w| {
417                 for f in self.fields_except_group() {
418                     f.write_clear(w);
419                 }
420                 w.write_line("self.unknown_fields.clear();");
421             });
422         });
423     }
424 
425     #[allow(dead_code)]
supports_derive_partial_eq(&self) -> bool426     fn supports_derive_partial_eq(&self) -> bool {
427         // There's stack overflow in the compiler when struct has too many fields
428         // https://github.com/rust-lang/rust/issues/40119
429         self.fields.len() <= 500
430     }
431 
write_struct(&self, w: &mut CodeWriter)432     fn write_struct(&self, w: &mut CodeWriter) {
433         let mut derive = vec!["PartialEq", "Clone", "Default"];
434         if self.lite_runtime {
435             derive.push("Debug");
436         }
437         w.derive(&derive);
438         serde::write_serde_attr(w, &self.customize, "derive(Serialize, Deserialize)");
439         w.pub_struct(&self.type_name, |w| {
440             if !self.fields_except_oneof().is_empty() {
441                 w.comment("message fields");
442                 for field in self.fields_except_oneof() {
443                     if field.proto_type == FieldDescriptorProto_Type::TYPE_GROUP {
444                         w.comment(&format!("{}: <group>", &field.rust_name));
445                     } else {
446                         let vis = if field.expose_field {
447                             Visibility::Public
448                         } else {
449                             match field.kind {
450                                 FieldKind::Repeated(..) => Visibility::Default,
451                                 FieldKind::Singular(SingularField { ref flag, .. }) => {
452                                     match *flag {
453                                         SingularFieldFlag::WithFlag { .. } => Visibility::Default,
454                                         SingularFieldFlag::WithoutFlag => Visibility::Public,
455                                     }
456                                 }
457                                 FieldKind::Map(..) => Visibility::Public,
458                                 FieldKind::Oneof(..) => unreachable!(),
459                             }
460                         };
461                         w.field_decl_vis(
462                             vis,
463                             &field.rust_name,
464                             &field.full_storage_type().to_code(&self.customize),
465                         );
466                     }
467                 }
468             }
469             if !self.oneofs().is_empty() {
470                 w.comment("message oneof groups");
471                 for oneof in self.oneofs() {
472                     let vis = match self.expose_oneof() {
473                         true => Visibility::Public,
474                         false => Visibility::Default,
475                     };
476                     w.field_decl_vis(
477                         vis,
478                         oneof.name(),
479                         &oneof.full_storage_type().to_code(&self.customize),
480                     );
481                 }
482             }
483             w.comment("special fields");
484             serde::write_serde_attr(w, &self.customize, "serde(skip)");
485             w.pub_field_decl(
486                 "unknown_fields",
487                 &format!("{}::UnknownFields", protobuf_crate_path(&self.customize)),
488             );
489             serde::write_serde_attr(w, &self.customize, "serde(skip)");
490             w.pub_field_decl(
491                 "cached_size",
492                 &format!("{}::CachedSize", protobuf_crate_path(&self.customize)),
493             );
494         });
495     }
496 
write_impl_default_for_amp(&self, w: &mut CodeWriter)497     fn write_impl_default_for_amp(&self, w: &mut CodeWriter) {
498         w.impl_args_for_block(
499             &["'a"],
500             "::std::default::Default",
501             &format!("&'a {}", self.type_name),
502             |w| {
503                 w.def_fn(&format!("default() -> &'a {}", self.type_name), |w| {
504                     w.write_line(&format!(
505                         "<{} as {}::Message>::default_instance()",
506                         self.type_name,
507                         protobuf_crate_path(&self.customize),
508                     ));
509                 });
510             },
511         );
512     }
513 
write(&self, w: &mut CodeWriter)514     pub fn write(&self, w: &mut CodeWriter) {
515         self.write_struct(w);
516 
517         w.write_line("");
518         self.write_impl_default_for_amp(w);
519 
520         for oneof in self.oneofs() {
521             w.write_line("");
522             oneof.write_enum(w);
523         }
524 
525         w.write_line("");
526         self.write_impl_self(w);
527         w.write_line("");
528         self.write_impl_message(w);
529         w.write_line("");
530         self.write_impl_clear(w);
531         if !self.lite_runtime {
532             w.write_line("");
533             self.write_impl_show(w);
534         }
535         w.write_line("");
536         self.write_impl_value(w);
537 
538         let mut nested_prefix = self.type_name.to_string();
539         nested_prefix.push_str("_");
540 
541         for nested in &self.message.to_scope().get_messages() {
542             // ignore map entries, because they are not used in map fields
543             if nested.map_entry().is_none() {
544                 w.write_line("");
545                 MessageGen::new(nested, self.root_scope, &self.customize).write(w);
546             }
547         }
548 
549         for enum_type in &self.message.to_scope().get_enums() {
550             w.write_line("");
551             let current_file = self.message.get_scope().get_file_descriptor();
552             EnumGen::new(enum_type, current_file, &self.customize, self.root_scope).write(w);
553         }
554     }
555 }
556