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