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