1 use std::fmt;
2
3 use protobuf::descriptor::*;
4 use protobuf::reflect::FileDescriptor;
5 use protobuf::reflect::MessageDescriptor;
6 use protobuf_parse::snake_case;
7
8 use crate::customize::ctx::CustomizeElemCtx;
9 use crate::customize::ctx::SpecialFieldPseudoDescriptor;
10 use crate::customize::rustproto_proto::customize_from_rustproto_for_message;
11 use crate::gen::code_writer::*;
12 use crate::gen::descriptor::write_fn_descriptor;
13 use crate::gen::enums::*;
14 use crate::gen::field::FieldGen;
15 use crate::gen::field::FieldKind;
16 use crate::gen::file_and_mod::FileAndMod;
17 use crate::gen::inside::protobuf_crate_path;
18 use crate::gen::oneof::OneofGen;
19 use crate::gen::oneof::OneofVariantGen;
20 use crate::gen::protoc_insertion_point::write_protoc_insertion_point_for_message;
21 use crate::gen::protoc_insertion_point::write_protoc_insertion_point_for_special_field;
22 use crate::gen::rust::ident::RustIdent;
23 use crate::gen::rust::ident_with_path::RustIdentWithPath;
24 use crate::gen::rust::rel_path::RustRelativePath;
25 use crate::gen::rust::snippets::expr_vec_with_capacity_const;
26 use crate::gen::rust::snippets::EXPR_NONE;
27 use crate::gen::rust_types_values::*;
28 use crate::gen::scope::MessageWithScope;
29 use crate::gen::scope::RootScope;
30 use crate::gen::scope::WithScope;
31 use crate::Customize;
32
33 /// Protobuf message Rust type name
34 #[derive(Debug, Clone, PartialEq, Eq)]
35 pub(crate) struct RustTypeMessage(pub RustIdentWithPath);
36
37 impl fmt::Display for RustTypeMessage {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 fmt::Display::fmt(&self.0, f)
40 }
41 }
42
43 impl<S: Into<RustIdentWithPath>> From<S> for RustTypeMessage {
from(s: S) -> Self44 fn from(s: S) -> Self {
45 RustTypeMessage(s.into())
46 }
47 }
48
49 impl RustTypeMessage {
50 /// Code which emits default instance.
default_instance(&self, customize: &Customize) -> String51 pub fn default_instance(&self, customize: &Customize) -> String {
52 format!(
53 "<{} as {}::Message>::default_instance()",
54 self.0,
55 protobuf_crate_path(customize)
56 )
57 }
58 }
59
60 /// Message info for codegen
61 pub(crate) struct MessageGen<'a> {
62 file_descriptor: &'a FileDescriptor,
63 message_descriptor: MessageDescriptor,
64 pub message: &'a MessageWithScope<'a>,
65 pub root_scope: &'a RootScope<'a>,
66 pub fields: Vec<FieldGen<'a>>,
67 pub lite_runtime: bool,
68 customize: CustomizeElemCtx<'a>,
69 path: &'a [i32],
70 info: Option<&'a SourceCodeInfo>,
71 }
72
73 impl<'a> MessageGen<'a> {
new( file_descriptor: &'a FileDescriptor, message: &'a MessageWithScope<'a>, root_scope: &'a RootScope<'a>, parent_customize: &CustomizeElemCtx<'a>, path: &'a [i32], info: Option<&'a SourceCodeInfo>, ) -> anyhow::Result<MessageGen<'a>>74 pub fn new(
75 file_descriptor: &'a FileDescriptor,
76 message: &'a MessageWithScope<'a>,
77 root_scope: &'a RootScope<'a>,
78 parent_customize: &CustomizeElemCtx<'a>,
79 path: &'a [i32],
80 info: Option<&'a SourceCodeInfo>,
81 ) -> anyhow::Result<MessageGen<'a>> {
82 let message_descriptor = file_descriptor
83 .message_by_package_relative_name(&format!("{}", message.protobuf_name_to_package()))
84 .unwrap();
85
86 let customize = parent_customize.child(
87 &customize_from_rustproto_for_message(message.message.proto().options.get_or_default()),
88 &message.message,
89 );
90
91 static FIELD_NUMBER: protobuf::rt::Lazy<i32> = protobuf::rt::Lazy::new();
92 let field_number = *FIELD_NUMBER.get(|| {
93 protobuf::reflect::MessageDescriptor::for_type::<DescriptorProto>()
94 .field_by_name("field")
95 .expect("`field` must exist")
96 .proto()
97 .number()
98 });
99
100 let fields: Vec<_> = message
101 .fields()
102 .into_iter()
103 .enumerate()
104 .map(|(id, field)| {
105 let mut path = path.to_vec();
106 path.extend_from_slice(&[field_number, id as i32]);
107 FieldGen::parse(field, root_scope, &customize, path, info)
108 })
109 .collect::<anyhow::Result<Vec<_>>>()?;
110 let lite_runtime = customize.for_elem.lite_runtime.unwrap_or_else(|| {
111 message.file_descriptor().proto().options.optimize_for()
112 == file_options::OptimizeMode::LITE_RUNTIME
113 });
114 Ok(MessageGen {
115 message_descriptor,
116 file_descriptor,
117 message,
118 root_scope,
119 fields,
120 lite_runtime,
121 customize,
122 path,
123 info,
124 })
125 }
126
rust_name(&self) -> RustIdent127 fn rust_name(&self) -> RustIdent {
128 self.message.rust_name()
129 }
130
mod_name(&self) -> RustRelativePath131 fn mod_name(&self) -> RustRelativePath {
132 self.message.scope.rust_path_to_file()
133 }
134
file_and_mod(&self) -> FileAndMod135 pub fn file_and_mod(&self) -> FileAndMod {
136 self.message
137 .scope
138 .file_and_mod(self.customize.for_elem.clone())
139 }
140
oneofs(&'a self) -> Vec<OneofGen<'a>>141 fn oneofs(&'a self) -> Vec<OneofGen<'a>> {
142 self.message
143 .oneofs()
144 .into_iter()
145 .map(|oneof| OneofGen::parse(self, oneof, &self.customize))
146 .collect()
147 }
148
required_fields(&'a self) -> Vec<&'a FieldGen>149 fn required_fields(&'a self) -> Vec<&'a FieldGen> {
150 self.fields
151 .iter()
152 .filter(|f| match f.kind {
153 FieldKind::Singular(ref singular) => singular.flag.is_required(),
154 _ => false,
155 })
156 .collect()
157 }
158
message_fields(&'a self) -> Vec<&'a FieldGen>159 fn message_fields(&'a self) -> Vec<&'a FieldGen> {
160 self.fields
161 .iter()
162 .filter(|f| f.proto_type == field_descriptor_proto::Type::TYPE_MESSAGE)
163 .collect()
164 }
165
fields_except_oneof(&'a self) -> Vec<&'a FieldGen>166 fn fields_except_oneof(&'a self) -> Vec<&'a FieldGen> {
167 self.fields
168 .iter()
169 .filter(|f| match f.kind {
170 FieldKind::Oneof(..) => false,
171 _ => true,
172 })
173 .collect()
174 }
175
fields_except_group(&'a self) -> Vec<&'a FieldGen>176 fn fields_except_group(&'a self) -> Vec<&'a FieldGen> {
177 self.fields
178 .iter()
179 .filter(|f| f.proto_type != field_descriptor_proto::Type::TYPE_GROUP)
180 .collect()
181 }
182
fields_except_oneof_and_group(&'a self) -> Vec<&'a FieldGen>183 fn fields_except_oneof_and_group(&'a self) -> Vec<&'a FieldGen> {
184 self.fields
185 .iter()
186 .filter(|f| match f.kind {
187 FieldKind::Oneof(..) => false,
188 _ => f.proto_type != field_descriptor_proto::Type::TYPE_GROUP,
189 })
190 .collect()
191 }
192
write_match_each_oneof_variant<F>(&self, w: &mut CodeWriter, cb: F) where F: Fn(&mut CodeWriter, &OneofVariantGen, &RustValueTyped),193 fn write_match_each_oneof_variant<F>(&self, w: &mut CodeWriter, cb: F)
194 where
195 F: Fn(&mut CodeWriter, &OneofVariantGen, &RustValueTyped),
196 {
197 for oneof in self.oneofs() {
198 let variants = oneof.variants_except_group();
199 if variants.is_empty() {
200 // Special case because
201 // https://github.com/rust-lang/rust/issues/50642
202 continue;
203 }
204 w.if_let_stmt(
205 "::std::option::Option::Some(ref v)",
206 &format!("self.{}", oneof.oneof.field_name())[..],
207 |w| {
208 w.match_block("v", |w| {
209 for variant in variants {
210 let ref field = variant.field;
211
212 let (refv, vtype) = if field.elem_type_is_copy() {
213 ("v", variant.rust_type(&self.file_and_mod()))
214 } else {
215 ("ref v", variant.rust_type(&self.file_and_mod()).ref_type())
216 };
217 w.case_block(
218 format!("&{}({})", variant.path(&self.file_and_mod()), refv),
219 |w| {
220 cb(
221 w,
222 &variant,
223 &RustValueTyped {
224 value: "v".to_owned(),
225 rust_type: vtype.clone(),
226 },
227 );
228 },
229 );
230 }
231 });
232 },
233 );
234 }
235 }
236
write_write_to_with_cached_sizes(&self, w: &mut CodeWriter)237 fn write_write_to_with_cached_sizes(&self, w: &mut CodeWriter) {
238 let sig = format!(
239 "write_to_with_cached_sizes(&self, os: &mut {protobuf_crate}::CodedOutputStream<'_>) -> {protobuf_crate}::Result<()>",
240 protobuf_crate=protobuf_crate_path(&self.customize.for_elem),
241 );
242 w.def_fn(&sig, |w| {
243 // To have access to its methods but not polute the name space.
244 for f in self.fields_except_oneof_and_group() {
245 f.write_message_write_field("os", w);
246 }
247 self.write_match_each_oneof_variant(w, |w, variant, v| {
248 variant
249 .field
250 .write_write_element(variant.elem(), w, "os", v);
251 });
252 w.write_line("os.write_unknown_fields(self.special_fields.unknown_fields())?;");
253 w.write_line("::std::result::Result::Ok(())");
254 });
255 }
256
write_default_instance_lazy(&self, w: &mut CodeWriter)257 fn write_default_instance_lazy(&self, w: &mut CodeWriter) {
258 w.lazy_static_decl_get_simple(
259 "instance",
260 &format!("{}", self.rust_name()),
261 &format!("{}::new", self.rust_name()),
262 &format!("{}", protobuf_crate_path(&self.customize.for_elem)),
263 );
264 }
265
write_default_instance_static(&self, w: &mut CodeWriter)266 fn write_default_instance_static(&self, w: &mut CodeWriter) {
267 w.stmt_block(
268 &format!(
269 "static instance: {} = {}",
270 self.rust_name(),
271 self.rust_name()
272 ),
273 |w| {
274 for f in &self.fields_except_oneof_and_group() {
275 w.field_entry(
276 &f.rust_name.to_string(),
277 &f.kind
278 .default(&self.customize.for_elem, &self.file_and_mod(), true),
279 );
280 }
281 for o in &self.oneofs() {
282 w.field_entry(&o.oneof.field_name().to_string(), EXPR_NONE);
283 }
284 w.field_entry(
285 "special_fields",
286 &format!(
287 "{}::SpecialFields::new()",
288 protobuf_crate_path(&self.customize.for_elem)
289 ),
290 );
291 },
292 );
293 w.write_line("&instance");
294 }
295
write_default_instance(&self, w: &mut CodeWriter)296 fn write_default_instance(&self, w: &mut CodeWriter) {
297 w.def_fn(
298 &format!("default_instance() -> &'static {}", self.rust_name()),
299 |w| {
300 let has_map_field = self.fields.iter().any(|f| match f.kind {
301 FieldKind::Map(..) => true,
302 _ => false,
303 });
304 if has_map_field {
305 self.write_default_instance_lazy(w)
306 } else {
307 self.write_default_instance_static(w)
308 }
309 },
310 );
311 }
312
write_compute_size(&self, w: &mut CodeWriter)313 fn write_compute_size(&self, w: &mut CodeWriter) {
314 // Append sizes of messages in the tree to the specified vector.
315 // First appended element is size of self, and then nested message sizes.
316 // in serialization order are appended recursively.");
317 w.comment("Compute sizes of nested messages");
318 // there are unused variables in oneof
319 w.allow(&["unused_variables"]);
320 w.def_fn("compute_size(&self) -> u64", |w| {
321 // To have access to its methods but not polute the name space.
322 w.write_line("let mut my_size = 0;");
323 for field in self.fields_except_oneof_and_group() {
324 field.write_message_compute_field_size("my_size", w);
325 }
326 self.write_match_each_oneof_variant(w, |w, variant, v| {
327 variant
328 .field
329 .write_element_size(variant.elem(), w, v, "my_size");
330 });
331 w.write_line(&format!(
332 "my_size += {}::rt::unknown_fields_size(self.special_fields.unknown_fields());",
333 protobuf_crate_path(&self.customize.for_elem)
334 ));
335 w.write_line("self.special_fields.cached_size().set(my_size as u32);");
336 w.write_line("my_size");
337 });
338 }
339
write_field_accessors(&self, w: &mut CodeWriter)340 fn write_field_accessors(&self, w: &mut CodeWriter) {
341 for f in self.fields_except_group() {
342 f.write_message_single_field_accessors(w);
343 }
344 }
345
write_impl_self(&self, w: &mut CodeWriter)346 fn write_impl_self(&self, w: &mut CodeWriter) {
347 w.impl_self_block(&format!("{}", self.rust_name()), |w| {
348 w.pub_fn(&format!("new() -> {}", self.rust_name()), |w| {
349 w.write_line("::std::default::Default::default()");
350 });
351
352 self.write_field_accessors(w);
353
354 if !self.lite_runtime {
355 w.write_line("");
356 self.write_generated_message_descriptor_data(w);
357 }
358 });
359 }
360
write_unknown_fields(&self, w: &mut CodeWriter)361 fn write_unknown_fields(&self, w: &mut CodeWriter) {
362 let sig = format!(
363 "special_fields(&self) -> &{}::SpecialFields",
364 protobuf_crate_path(&self.customize.for_elem)
365 );
366 w.def_fn(&sig, |w| {
367 w.write_line("&self.special_fields");
368 });
369 w.write_line("");
370 let sig = format!(
371 "mut_special_fields(&mut self) -> &mut {}::SpecialFields",
372 protobuf_crate_path(&self.customize.for_elem)
373 );
374 w.def_fn(&sig, |w| {
375 w.write_line("&mut self.special_fields");
376 });
377 }
378
write_merge_from(&self, w: &mut CodeWriter)379 fn write_merge_from(&self, w: &mut CodeWriter) {
380 let sig = format!(
381 "merge_from(&mut self, is: &mut {}::CodedInputStream<'_>) -> {}::Result<()>",
382 protobuf_crate_path(&self.customize.for_elem),
383 protobuf_crate_path(&self.customize.for_elem),
384 );
385 w.def_fn(&sig, |w| {
386 w.while_block("let Some(tag) = is.read_raw_tag_or_eof()?", |w| {
387 w.match_block("tag", |w| {
388 for f in &self.fields_except_group() {
389 f.write_merge_from_field_case_block(w);
390 }
391 w.case_block("tag", |w| {
392 w.write_line(&format!("{}::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;", protobuf_crate_path(&self.customize.for_elem)));
393 });
394 });
395 });
396 w.write_line("::std::result::Result::Ok(())");
397 });
398 }
399
write_impl_message_full_fn_descriptor(&self, w: &mut CodeWriter)400 fn write_impl_message_full_fn_descriptor(&self, w: &mut CodeWriter) {
401 write_fn_descriptor(
402 &self.message.message,
403 self.message.scope(),
404 &self.customize.for_elem,
405 w,
406 );
407 }
408
write_generated_message_descriptor_data(&self, w: &mut CodeWriter)409 fn write_generated_message_descriptor_data(&self, w: &mut CodeWriter) {
410 let sig = format!(
411 "generated_message_descriptor_data() -> {}::reflect::GeneratedMessageDescriptorData",
412 protobuf_crate_path(&self.customize.for_elem)
413 );
414 w.fn_block(
415 Visibility::Path(self.message.scope().rust_path_to_file().to_reverse()),
416 &sig,
417 |w| {
418 let fields = self.fields_except_group();
419 let oneofs = self.oneofs();
420 w.write_line(&format!(
421 "let mut fields = {};",
422 expr_vec_with_capacity_const(fields.len())
423 ));
424 w.write_line(&format!(
425 "let mut oneofs = {};",
426 expr_vec_with_capacity_const(oneofs.len())
427 ));
428 for field in fields {
429 field.write_push_accessor("fields", w);
430 }
431 for oneof in oneofs {
432 w.write_line(&format!(
433 "oneofs.push({}::generated_oneof_descriptor_data());",
434 oneof.type_name_relative(&self.mod_name())
435 ));
436 }
437 w.write_line(&format!(
438 "{}::reflect::GeneratedMessageDescriptorData::new_2::<{}>(",
439 protobuf_crate_path(&self.customize.for_elem),
440 self.rust_name(),
441 ));
442 w.indented(|w| {
443 w.write_line(&format!("\"{}\",", self.message.name_to_package()));
444 w.write_line("fields,");
445 w.write_line("oneofs,");
446 });
447 w.write_line(")");
448 },
449 );
450 }
451
write_is_initialized(&self, w: &mut CodeWriter)452 fn write_is_initialized(&self, w: &mut CodeWriter) {
453 w.def_fn(&format!("is_initialized(&self) -> bool"), |w| {
454 if !self.message.message.is_initialized_is_always_true() {
455 // TODO: use single loop
456
457 for f in self.required_fields() {
458 f.write_if_self_field_is_none(w, |w| {
459 w.write_line("return false;");
460 });
461 }
462
463 for f in self.message_fields() {
464 if let FieldKind::Map(..) = f.kind {
465 // TODO
466 w.comment("TODO: check map values are initialized");
467 continue;
468 }
469
470 f.write_for_self_field(w, "v", |w, _t| {
471 w.if_stmt("!v.is_initialized()", |w| {
472 w.write_line("return false;");
473 });
474 });
475 }
476 }
477 w.write_line("true");
478 });
479 }
480
write_impl_message(&self, w: &mut CodeWriter)481 fn write_impl_message(&self, w: &mut CodeWriter) {
482 w.impl_for_block(
483 &format!("{}::Message", protobuf_crate_path(&self.customize.for_elem),),
484 &format!("{}", self.rust_name()),
485 |w| {
486 w.write_line(&format!(
487 "const NAME: &'static str = \"{}\";",
488 self.message.message.name()
489 ));
490 w.write_line("");
491 self.write_is_initialized(w);
492 w.write_line("");
493 self.write_merge_from(w);
494 w.write_line("");
495 self.write_compute_size(w);
496 w.write_line("");
497 self.write_write_to_with_cached_sizes(w);
498 w.write_line("");
499 self.write_unknown_fields(w);
500 w.write_line("");
501 w.def_fn(&format!("new() -> {}", self.rust_name()), |w| {
502 w.write_line(&format!("{}::new()", self.rust_name()));
503 });
504 w.write_line("");
505 w.def_fn("clear(&mut self)", |w| {
506 for f in self.fields_except_group() {
507 f.write_clear(w);
508 }
509 w.write_line("self.special_fields.clear();");
510 });
511 w.write_line("");
512 self.write_default_instance(w);
513 },
514 );
515 }
516
write_impl_message_full(&self, w: &mut CodeWriter)517 fn write_impl_message_full(&self, w: &mut CodeWriter) {
518 w.impl_for_block(
519 &format!(
520 "{}::MessageFull",
521 protobuf_crate_path(&self.customize.for_elem),
522 ),
523 &format!("{}", self.rust_name()),
524 |w| {
525 self.write_impl_message_full_fn_descriptor(w);
526 },
527 );
528 }
529
write_impl_value(&self, w: &mut CodeWriter)530 fn write_impl_value(&self, w: &mut CodeWriter) {
531 w.impl_for_block(
532 &format!(
533 "{}::reflect::ProtobufValue",
534 protobuf_crate_path(&self.customize.for_elem)
535 ),
536 &format!("{}", self.rust_name()),
537 |w| {
538 w.write_line(&format!(
539 "type RuntimeType = {}::reflect::rt::RuntimeTypeMessage<Self>;",
540 protobuf_crate_path(&self.customize.for_elem)
541 ));
542 },
543 )
544 }
545
write_impl_display(&self, w: &mut CodeWriter)546 fn write_impl_display(&self, w: &mut CodeWriter) {
547 w.impl_for_block(
548 "::std::fmt::Display",
549 &format!("{}", self.rust_name()),
550 |w| {
551 w.def_fn(
552 "fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result",
553 |w| {
554 w.write_line(&format!(
555 "{}::text_format::fmt(self, f)",
556 protobuf_crate_path(&self.customize.for_elem)
557 ));
558 },
559 );
560 },
561 );
562 }
563
supports_derive_partial_eq(&self) -> bool564 fn supports_derive_partial_eq(&self) -> bool {
565 // There's stack overflow in the compiler when struct has too many fields
566 // https://github.com/rust-lang/rust/issues/40119
567 self.fields.len() <= 500
568 }
569
write_struct(&self, w: &mut CodeWriter)570 fn write_struct(&self, w: &mut CodeWriter) {
571 let mut derive = Vec::new();
572 if self.supports_derive_partial_eq() {
573 derive.push("PartialEq");
574 }
575 derive.extend(&["Clone", "Default", "Debug"]);
576 w.derive(&derive);
577 write_protoc_insertion_point_for_message(
578 w,
579 &self.customize.for_elem,
580 &self.message_descriptor,
581 );
582 w.pub_struct(&format!("{}", self.rust_name()), |w| {
583 if !self.fields_except_oneof().is_empty() {
584 w.comment("message fields");
585 for field in self.fields_except_oneof() {
586 field.write_struct_field(w);
587 }
588 }
589 if !self.oneofs().is_empty() {
590 w.comment("message oneof groups");
591 for oneof in self.oneofs() {
592 w.field_decl_vis(
593 Visibility::Public,
594 &oneof.oneof.field_name().to_string(),
595 &oneof.full_storage_type().to_code(&self.customize.for_elem),
596 );
597 }
598 }
599 w.comment("special fields");
600
601 let customize_special_fields = self
602 .customize
603 .child(
604 &Customize::default(),
605 &SpecialFieldPseudoDescriptor {
606 message: &self.message.message,
607 field: "special_fields",
608 },
609 )
610 .for_elem;
611
612 write_protoc_insertion_point_for_special_field(
613 w,
614 &customize_special_fields,
615 &self.message_descriptor,
616 "special_fields",
617 );
618 w.pub_field_decl(
619 "special_fields",
620 &format!(
621 "{}::SpecialFields",
622 protobuf_crate_path(&self.customize.for_elem)
623 ),
624 );
625 });
626 }
627
write_impl_default_for_amp(&self, w: &mut CodeWriter)628 fn write_impl_default_for_amp(&self, w: &mut CodeWriter) {
629 w.impl_args_for_block(
630 &["'a"],
631 "::std::default::Default",
632 &format!("&'a {}", self.rust_name()),
633 |w| {
634 w.def_fn(&format!("default() -> &'a {}", self.rust_name()), |w| {
635 w.write_line(&format!(
636 "<{} as {}::Message>::default_instance()",
637 self.rust_name(),
638 protobuf_crate_path(&self.customize.for_elem),
639 ));
640 });
641 },
642 );
643 }
644
write_dummy_impl_partial_eq(&self, w: &mut CodeWriter)645 fn write_dummy_impl_partial_eq(&self, w: &mut CodeWriter) {
646 w.impl_for_block(
647 "::std::cmp::PartialEq",
648 &format!("{}", self.rust_name()),
649 |w| {
650 w.def_fn("eq(&self, _: &Self) -> bool", |w| {
651 w.comment("https://github.com/rust-lang/rust/issues/40119");
652 w.unimplemented();
653 });
654 },
655 );
656 }
657
write(&self, w: &mut CodeWriter) -> anyhow::Result<()>658 pub fn write(&self, w: &mut CodeWriter) -> anyhow::Result<()> {
659 w.all_documentation(self.info, self.path);
660 self.write_struct(w);
661
662 w.write_line("");
663 self.write_impl_default_for_amp(w);
664
665 if !self.supports_derive_partial_eq() {
666 w.write_line("");
667 self.write_dummy_impl_partial_eq(w);
668 }
669
670 w.write_line("");
671 self.write_impl_self(w);
672 w.write_line("");
673 self.write_impl_message(w);
674 if !self.lite_runtime {
675 w.write_line("");
676 self.write_impl_message_full(w);
677 }
678 if !self.lite_runtime {
679 w.write_line("");
680 self.write_impl_display(w);
681
682 w.write_line("");
683 self.write_impl_value(w);
684 }
685
686 let mod_name = message_name_to_nested_mod_name(&self.message.message.name());
687
688 let oneofs = self.oneofs();
689 let nested_messages: Vec<_> = self
690 .message
691 .to_scope()
692 .messages()
693 .into_iter()
694 .filter(|nested| {
695 // ignore map entries, because they are not used in map fields
696 !nested.is_map()
697 })
698 .collect();
699 let nested_enums = self.message.to_scope().enums();
700
701 if !oneofs.is_empty() || !nested_messages.is_empty() || !nested_enums.is_empty() {
702 w.write_line("");
703 w.write_line(&format!(
704 "/// Nested message and enums of message `{}`",
705 self.message.message.name()
706 ));
707 w.pub_mod(&mod_name.to_string(), |w| {
708 let mut first = true;
709
710 for oneof in &oneofs {
711 w.write_line("");
712 oneof.write(w);
713 }
714
715 static NESTED_TYPE_NUMBER: protobuf::rt::Lazy<i32> = protobuf::rt::Lazy::new();
716 let nested_type_number = *NESTED_TYPE_NUMBER.get(|| {
717 MessageDescriptor::for_type::<DescriptorProto>()
718 .field_by_name("nested_type")
719 .expect("`nested_type` must exist")
720 .proto()
721 .number()
722 });
723
724 let mut path = self.path.to_vec();
725 path.extend(&[nested_type_number, 0]);
726 for (id, nested) in nested_messages.iter().enumerate() {
727 let len = path.len() - 1;
728 path[len] = id as i32;
729
730 if !first {
731 w.write_line("");
732 }
733 first = false;
734 MessageGen::new(
735 &self.file_descriptor,
736 nested,
737 self.root_scope,
738 &self.customize,
739 &path,
740 self.info,
741 )
742 // TODO: do not unwrap.
743 .unwrap()
744 .write(w)
745 // TODO: do not unwrap.
746 .unwrap();
747 }
748
749 static ENUM_TYPE_NUMBER: protobuf::rt::Lazy<i32> = protobuf::rt::Lazy::new();
750 let enum_type_number = *ENUM_TYPE_NUMBER.get(|| {
751 MessageDescriptor::for_type::<DescriptorProto>()
752 .field_by_name("enum_type")
753 .expect("`enum_type` must exist")
754 .proto()
755 .number()
756 });
757
758 let len = path.len() - 2;
759 path[len] = enum_type_number;
760 for (id, enum_type) in self.message.to_scope().enums().iter().enumerate() {
761 let len = path.len() - 1;
762 path[len] = id as i32;
763
764 if !first {
765 w.write_line("");
766 }
767 first = false;
768 EnumGen::new(
769 enum_type,
770 &self.customize,
771 self.root_scope,
772 &path,
773 self.info,
774 )
775 .write(w);
776 }
777 });
778 }
779 Ok(())
780 }
781 }
782
message_name_to_nested_mod_name(message_name: &str) -> RustIdent783 pub(crate) fn message_name_to_nested_mod_name(message_name: &str) -> RustIdent {
784 let mod_name = snake_case(message_name);
785 RustIdent::new(&mod_name)
786 }
787