1use std::ascii;
2use std::borrow::Cow;
3use std::collections::{HashMap, HashSet};
4use std::iter;
5
6use itertools::{Either, Itertools};
7use log::debug;
8use multimap::MultiMap;
9use prost_types::field_descriptor_proto::{Label, Type};
10use prost_types::source_code_info::Location;
11use prost_types::{
12 DescriptorProto, EnumDescriptorProto, EnumValueDescriptorProto, FieldDescriptorProto,
13 FieldOptions, FileDescriptorProto, OneofDescriptorProto, ServiceDescriptorProto,
14 SourceCodeInfo,
15};
16
17use crate::ast::{Comments, Method, Service};
18use crate::context::Context;
19use crate::ident::{strip_enum_prefix, to_snake, to_upper_camel};
20use crate::Config;
21
22mod c_escaping;
23use c_escaping::unescape_c_escape_string;
24
25mod syntax;
26use syntax::Syntax;
27
28pub struct CodeGenerator<'a, 'b> {
30 context: &'a mut Context<'b>,
31 package: String,
32 type_path: Vec<String>,
33 source_info: Option<SourceCodeInfo>,
34 syntax: Syntax,
35 depth: u8,
36 path: Vec<i32>,
37 buf: &'a mut String,
38}
39
40fn push_indent(buf: &mut String, depth: u8) {
41 for _ in 0..depth {
42 buf.push_str(" ");
43 }
44}
45
46struct Field {
47 descriptor: FieldDescriptorProto,
48 path_index: i32,
49}
50
51impl Field {
52 fn new(descriptor: FieldDescriptorProto, path_index: i32) -> Self {
53 Self {
54 descriptor,
55 path_index,
56 }
57 }
58
59 fn rust_name(&self) -> String {
60 to_snake(self.descriptor.name())
61 }
62}
63
64struct OneofField {
65 descriptor: OneofDescriptorProto,
66 fields: Vec<Field>,
67 path_index: i32,
68}
69
70impl OneofField {
71 fn new(descriptor: OneofDescriptorProto, fields: Vec<Field>, path_index: i32) -> Self {
72 Self {
73 descriptor,
74 fields,
75 path_index,
76 }
77 }
78
79 fn rust_name(&self) -> String {
80 to_snake(self.descriptor.name())
81 }
82}
83
84impl<'b> CodeGenerator<'_, 'b> {
85 fn config(&self) -> &Config {
86 self.context.config()
87 }
88
89 pub(crate) fn generate(context: &mut Context<'b>, file: FileDescriptorProto, buf: &mut String) {
90 let source_info = file.source_code_info.map(|mut s| {
91 s.location.retain(|loc| {
92 let len = loc.path.len();
93 len > 0 && len % 2 == 0
94 });
95 s.location.sort_by(|a, b| a.path.cmp(&b.path));
96 s
97 });
98
99 let mut code_gen = CodeGenerator {
100 context,
101 package: file.package.unwrap_or_default(),
102 type_path: Vec::new(),
103 source_info,
104 syntax: file.syntax.as_deref().into(),
105 depth: 0,
106 path: Vec::new(),
107 buf,
108 };
109
110 debug!(
111 "file: {:?}, package: {:?}",
112 file.name.as_ref().unwrap(),
113 code_gen.package
114 );
115
116 code_gen.path.push(4);
117 for (idx, message) in file.message_type.into_iter().enumerate() {
118 code_gen.path.push(idx as i32);
119 code_gen.append_message(message);
120 code_gen.path.pop();
121 }
122 code_gen.path.pop();
123
124 code_gen.path.push(5);
125 for (idx, desc) in file.enum_type.into_iter().enumerate() {
126 code_gen.path.push(idx as i32);
127 code_gen.append_enum(desc);
128 code_gen.path.pop();
129 }
130 code_gen.path.pop();
131
132 if code_gen.context.service_generator_mut().is_some() {
133 code_gen.path.push(6);
134 for (idx, service) in file.service.into_iter().enumerate() {
135 code_gen.path.push(idx as i32);
136 code_gen.push_service(service);
137 code_gen.path.pop();
138 }
139
140 if let Some(service_generator) = code_gen.context.service_generator_mut() {
141 service_generator.finalize(code_gen.buf);
142 }
143
144 code_gen.path.pop();
145 }
146 }
147
148 fn append_message(&mut self, message: DescriptorProto) {
149 debug!(" message: {:?}", message.name());
150
151 let message_name = message.name().to_string();
152 let fq_message_name = self.fq_name(&message_name);
153
154 if self
156 .context
157 .resolve_extern_ident(&fq_message_name)
158 .is_some()
159 {
160 return;
161 }
162
163 type NestedTypes = Vec<(DescriptorProto, usize)>;
167 type MapTypes = HashMap<String, (FieldDescriptorProto, FieldDescriptorProto)>;
168 let (nested_types, map_types): (NestedTypes, MapTypes) = message
169 .nested_type
170 .into_iter()
171 .enumerate()
172 .partition_map(|(idx, nested_type)| {
173 if nested_type
174 .options
175 .as_ref()
176 .and_then(|options| options.map_entry)
177 .unwrap_or(false)
178 {
179 let key = nested_type.field[0].clone();
180 let value = nested_type.field[1].clone();
181 assert_eq!("key", key.name());
182 assert_eq!("value", value.name());
183
184 let name = format!("{}.{}", &fq_message_name, nested_type.name());
185 Either::Right((name, (key, value)))
186 } else {
187 Either::Left((nested_type, idx))
188 }
189 });
190
191 type OneofFieldsByIndex = MultiMap<i32, Field>;
194 let (fields, mut oneof_map): (Vec<Field>, OneofFieldsByIndex) = message
195 .field
196 .into_iter()
197 .enumerate()
198 .partition_map(|(idx, proto)| {
199 let idx = idx as i32;
200 if proto.proto3_optional.unwrap_or(false) {
201 Either::Left(Field::new(proto, idx))
202 } else if let Some(oneof_index) = proto.oneof_index {
203 Either::Right((oneof_index, Field::new(proto, idx)))
204 } else {
205 Either::Left(Field::new(proto, idx))
206 }
207 });
208 let oneof_fields: Vec<OneofField> = message
210 .oneof_decl
211 .into_iter()
212 .enumerate()
213 .filter_map(move |(idx, proto)| {
214 let idx = idx as i32;
215 oneof_map
216 .remove(&idx)
217 .map(|fields| OneofField::new(proto, fields, idx))
218 })
219 .collect();
220
221 self.append_doc(&fq_message_name, None);
222 self.append_type_attributes(&fq_message_name);
223 self.append_message_attributes(&fq_message_name);
224 self.push_indent();
225 self.buf.push_str(&format!(
226 "#[derive(Clone, {}PartialEq, {}{}::Message)]\n",
227 if self.context.can_message_derive_copy(&fq_message_name) {
228 "Copy, "
229 } else {
230 ""
231 },
232 if self.context.can_message_derive_eq(&fq_message_name) {
233 "Eq, Hash, "
234 } else {
235 ""
236 },
237 self.context.prost_path()
238 ));
239 self.append_skip_debug(&fq_message_name);
240 self.push_indent();
241 self.buf.push_str("pub struct ");
242 self.buf.push_str(&to_upper_camel(&message_name));
243 self.buf.push_str(" {\n");
244
245 self.depth += 1;
246 self.path.push(2);
247 for field in &fields {
248 self.path.push(field.path_index);
249 match field
250 .descriptor
251 .type_name
252 .as_ref()
253 .and_then(|type_name| map_types.get(type_name))
254 {
255 Some((key, value)) => self.append_map_field(&fq_message_name, field, key, value),
256 None => self.append_field(&fq_message_name, field),
257 }
258 self.path.pop();
259 }
260 self.path.pop();
261
262 self.path.push(8);
263 for oneof in &oneof_fields {
264 self.path.push(oneof.path_index);
265 self.append_oneof_field(&message_name, &fq_message_name, oneof);
266 self.path.pop();
267 }
268 self.path.pop();
269
270 self.depth -= 1;
271 self.push_indent();
272 self.buf.push_str("}\n");
273
274 if !message.enum_type.is_empty() || !nested_types.is_empty() || !oneof_fields.is_empty() {
275 self.push_mod(&message_name);
276 self.path.push(3);
277 for (nested_type, idx) in nested_types {
278 self.path.push(idx as i32);
279 self.append_message(nested_type);
280 self.path.pop();
281 }
282 self.path.pop();
283
284 self.path.push(4);
285 for (idx, nested_enum) in message.enum_type.into_iter().enumerate() {
286 self.path.push(idx as i32);
287 self.append_enum(nested_enum);
288 self.path.pop();
289 }
290 self.path.pop();
291
292 for oneof in &oneof_fields {
293 self.append_oneof(&fq_message_name, oneof);
294 }
295
296 self.pop_mod();
297 }
298
299 if self.config().enable_type_names {
300 self.append_type_name(&message_name, &fq_message_name);
301 }
302 }
303
304 fn append_type_name(&mut self, message_name: &str, fq_message_name: &str) {
305 let prost_path = self.context.prost_path();
306
307 self.buf.push_str(&format!(
308 "impl {prost_path}::Name for {} {{\n",
309 to_upper_camel(message_name)
310 ));
311 self.depth += 1;
312
313 self.buf.push_str(&format!(
314 "const NAME: &'static str = \"{}\";\n",
315 message_name,
316 ));
317 self.buf.push_str(&format!(
318 "const PACKAGE: &'static str = \"{}\";\n",
319 self.package,
320 ));
321
322 let string_path = format!("{prost_path}::alloc::string::String");
323
324 let full_name = format!(
325 "{}{}{}{}{message_name}",
326 self.package.trim_matches('.'),
327 if self.package.is_empty() { "" } else { "." },
328 self.type_path.join("."),
329 if self.type_path.is_empty() { "" } else { "." },
330 );
331 let domain_name = self.context.type_name_domain(fq_message_name);
332
333 self.buf.push_str(&format!(
334 r#"fn full_name() -> {string_path} {{ "{full_name}".into() }}"#,
335 ));
336
337 self.buf.push_str(&format!(
338 r#"fn type_url() -> {string_path} {{ "{domain_name}/{full_name}".into() }}"#,
339 ));
340
341 self.depth -= 1;
342 self.buf.push_str("}\n");
343 }
344
345 fn append_type_attributes(&mut self, fq_message_name: &str) {
346 assert_eq!(b'.', fq_message_name.as_bytes()[0]);
347 for attribute in self.context.type_attributes(fq_message_name) {
348 push_indent(self.buf, self.depth);
349 self.buf.push_str(attribute);
350 self.buf.push('\n');
351 }
352 }
353
354 fn append_message_attributes(&mut self, fq_message_name: &str) {
355 assert_eq!(b'.', fq_message_name.as_bytes()[0]);
356 for attribute in self.context.message_attributes(fq_message_name) {
357 push_indent(self.buf, self.depth);
358 self.buf.push_str(attribute);
359 self.buf.push('\n');
360 }
361 }
362
363 fn append_skip_debug(&mut self, fq_message_name: &str) {
364 if self.context.should_skip_debug(fq_message_name) {
365 push_indent(self.buf, self.depth);
366 self.buf.push_str("#[prost(skip_debug)]");
367 self.buf.push('\n');
368 }
369 }
370
371 fn append_enum_attributes(&mut self, fq_message_name: &str) {
372 assert_eq!(b'.', fq_message_name.as_bytes()[0]);
373 for attribute in self.context.enum_attributes(fq_message_name) {
374 push_indent(self.buf, self.depth);
375 self.buf.push_str(attribute);
376 self.buf.push('\n');
377 }
378 }
379
380 fn append_field_attributes(&mut self, fq_message_name: &str, field_name: &str) {
381 assert_eq!(b'.', fq_message_name.as_bytes()[0]);
382 for attribute in self.context.field_attributes(fq_message_name, field_name) {
383 push_indent(self.buf, self.depth);
384 self.buf.push_str(attribute);
385 self.buf.push('\n');
386 }
387 }
388
389 fn append_field(&mut self, fq_message_name: &str, field: &Field) {
390 let type_ = field.descriptor.r#type();
391 let repeated = field.descriptor.label() == Label::Repeated;
392 let deprecated = self.deprecated(&field.descriptor);
393 let optional = self.optional(&field.descriptor);
394 let boxed = self
395 .context
396 .should_box_message_field(fq_message_name, &field.descriptor);
397 let ty = self.resolve_type(&field.descriptor, fq_message_name);
398
399 debug!(
400 " field: {:?}, type: {:?}, boxed: {}",
401 field.descriptor.name(),
402 ty,
403 boxed
404 );
405
406 self.append_doc(fq_message_name, Some(field.descriptor.name()));
407
408 if deprecated {
409 self.push_indent();
410 self.buf.push_str("#[deprecated]\n");
411 }
412
413 self.push_indent();
414 self.buf.push_str("#[prost(");
415 let type_tag = self.field_type_tag(&field.descriptor);
416 self.buf.push_str(&type_tag);
417
418 if type_ == Type::Bytes {
419 let bytes_type = self
420 .context
421 .bytes_type(fq_message_name, field.descriptor.name());
422 self.buf
423 .push_str(&format!("={:?}", bytes_type.annotation()));
424 }
425
426 match field.descriptor.label() {
427 Label::Optional => {
428 if optional {
429 self.buf.push_str(", optional");
430 }
431 }
432 Label::Required => self.buf.push_str(", required"),
433 Label::Repeated => {
434 self.buf.push_str(", repeated");
435 if can_pack(&field.descriptor)
436 && !field
437 .descriptor
438 .options
439 .as_ref()
440 .map_or(self.syntax == Syntax::Proto3, |options| options.packed())
441 {
442 self.buf.push_str(", packed=\"false\"");
443 }
444 }
445 }
446
447 if boxed {
448 self.buf.push_str(", boxed");
449 }
450 self.buf.push_str(", tag=\"");
451 self.buf.push_str(&field.descriptor.number().to_string());
452
453 if let Some(ref default) = field.descriptor.default_value {
454 self.buf.push_str("\", default=\"");
455 if type_ == Type::Bytes {
456 self.buf.push_str("b\\\"");
457 for b in unescape_c_escape_string(default) {
458 self.buf.extend(
459 ascii::escape_default(b).flat_map(|c| (c as char).escape_default()),
460 );
461 }
462 self.buf.push_str("\\\"");
463 } else if type_ == Type::Enum {
464 let mut enum_value = to_upper_camel(default);
465 if self.config().strip_enum_prefix {
466 let enum_type = field
470 .descriptor
471 .type_name
472 .as_ref()
473 .and_then(|ty| ty.split('.').next_back())
474 .unwrap();
475
476 enum_value = strip_enum_prefix(&to_upper_camel(enum_type), &enum_value)
477 }
478 self.buf.push_str(&enum_value);
479 } else {
480 self.buf.push_str(&default.escape_default().to_string());
481 }
482 }
483
484 self.buf.push_str("\")]\n");
485 self.append_field_attributes(fq_message_name, field.descriptor.name());
486 self.push_indent();
487 self.buf.push_str("pub ");
488 self.buf.push_str(&field.rust_name());
489 self.buf.push_str(": ");
490
491 let prost_path = self.context.prost_path();
492
493 if repeated {
494 self.buf
495 .push_str(&format!("{}::alloc::vec::Vec<", prost_path));
496 } else if optional {
497 self.buf.push_str("::core::option::Option<");
498 }
499 if boxed {
500 self.buf
501 .push_str(&format!("{}::alloc::boxed::Box<", prost_path));
502 }
503 self.buf.push_str(&ty);
504 if boxed {
505 self.buf.push('>');
506 }
507 if repeated || optional {
508 self.buf.push('>');
509 }
510 self.buf.push_str(",\n");
511 }
512
513 fn append_map_field(
514 &mut self,
515 fq_message_name: &str,
516 field: &Field,
517 key: &FieldDescriptorProto,
518 value: &FieldDescriptorProto,
519 ) {
520 let key_ty = self.resolve_type(key, fq_message_name);
521 let value_ty = self.resolve_type(value, fq_message_name);
522
523 debug!(
524 " map field: {:?}, key type: {:?}, value type: {:?}",
525 field.descriptor.name(),
526 key_ty,
527 value_ty
528 );
529
530 self.append_doc(fq_message_name, Some(field.descriptor.name()));
531 self.push_indent();
532
533 let map_type = self
534 .context
535 .map_type(fq_message_name, field.descriptor.name());
536 let key_tag = self.field_type_tag(key);
537 let value_tag = self.map_value_type_tag(value);
538
539 self.buf.push_str(&format!(
540 "#[prost({}=\"{}, {}\", tag=\"{}\")]\n",
541 map_type.annotation(),
542 key_tag,
543 value_tag,
544 field.descriptor.number()
545 ));
546 self.append_field_attributes(fq_message_name, field.descriptor.name());
547 self.push_indent();
548 self.buf.push_str(&format!(
549 "pub {}: {}<{}, {}>,\n",
550 field.rust_name(),
551 map_type.rust_type(),
552 key_ty,
553 value_ty
554 ));
555 }
556
557 fn append_oneof_field(
558 &mut self,
559 message_name: &str,
560 fq_message_name: &str,
561 oneof: &OneofField,
562 ) {
563 let type_name = format!(
564 "{}::{}",
565 to_snake(message_name),
566 to_upper_camel(oneof.descriptor.name())
567 );
568 self.append_doc(fq_message_name, None);
569 self.push_indent();
570 self.buf.push_str(&format!(
571 "#[prost(oneof=\"{}\", tags=\"{}\")]\n",
572 type_name,
573 oneof
574 .fields
575 .iter()
576 .map(|field| field.descriptor.number())
577 .join(", "),
578 ));
579 self.append_field_attributes(fq_message_name, oneof.descriptor.name());
580 self.push_indent();
581 self.buf.push_str(&format!(
582 "pub {}: ::core::option::Option<{}>,\n",
583 oneof.rust_name(),
584 type_name
585 ));
586 }
587
588 fn append_oneof(&mut self, fq_message_name: &str, oneof: &OneofField) {
589 self.path.push(8);
590 self.path.push(oneof.path_index);
591 self.append_doc(fq_message_name, None);
592 self.path.pop();
593 self.path.pop();
594
595 let oneof_name = format!("{}.{}", fq_message_name, oneof.descriptor.name());
596 self.append_type_attributes(&oneof_name);
597 self.append_enum_attributes(&oneof_name);
598 self.push_indent();
599
600 let can_oneof_derive_copy = oneof.fields.iter().all(|field| {
601 self.context
602 .can_field_derive_copy(fq_message_name, &field.descriptor)
603 });
604 let can_oneof_derive_eq = oneof.fields.iter().all(|field| {
605 self.context
606 .can_field_derive_eq(fq_message_name, &field.descriptor)
607 });
608 self.buf.push_str(&format!(
609 "#[derive(Clone, {}PartialEq, {}{}::Oneof)]\n",
610 if can_oneof_derive_copy { "Copy, " } else { "" },
611 if can_oneof_derive_eq {
612 "Eq, Hash, "
613 } else {
614 ""
615 },
616 self.context.prost_path()
617 ));
618 self.append_skip_debug(fq_message_name);
619 self.push_indent();
620 self.buf.push_str("pub enum ");
621 self.buf.push_str(&to_upper_camel(oneof.descriptor.name()));
622 self.buf.push_str(" {\n");
623
624 self.path.push(2);
625 self.depth += 1;
626 for field in &oneof.fields {
627 self.path.push(field.path_index);
628 self.append_doc(fq_message_name, Some(field.descriptor.name()));
629 self.path.pop();
630
631 self.push_indent();
632 let ty_tag = self.field_type_tag(&field.descriptor);
633 self.buf.push_str(&format!(
634 "#[prost({}, tag=\"{}\")]\n",
635 ty_tag,
636 field.descriptor.number()
637 ));
638 self.append_field_attributes(&oneof_name, field.descriptor.name());
639
640 self.push_indent();
641 let ty = self.resolve_type(&field.descriptor, fq_message_name);
642
643 let boxed = self.context.should_box_oneof_field(
644 fq_message_name,
645 oneof.descriptor.name(),
646 &field.descriptor,
647 );
648
649 debug!(
650 " oneof: {:?}, type: {:?}, boxed: {}",
651 field.descriptor.name(),
652 ty,
653 boxed
654 );
655
656 if boxed {
657 self.buf.push_str(&format!(
658 "{}(::prost::alloc::boxed::Box<{}>),\n",
659 to_upper_camel(field.descriptor.name()),
660 ty
661 ));
662 } else {
663 self.buf.push_str(&format!(
664 "{}({}),\n",
665 to_upper_camel(field.descriptor.name()),
666 ty
667 ));
668 }
669 }
670 self.depth -= 1;
671 self.path.pop();
672
673 self.push_indent();
674 self.buf.push_str("}\n");
675 }
676
677 fn location(&self) -> Option<&Location> {
678 let source_info = self.source_info.as_ref()?;
679 let idx = source_info
680 .location
681 .binary_search_by_key(&&self.path[..], |location| &location.path[..])
682 .unwrap();
683 Some(&source_info.location[idx])
684 }
685
686 fn append_doc(&mut self, fq_name: &str, field_name: Option<&str>) {
687 if !self.context.should_disable_comments(fq_name, field_name) {
688 if let Some(comments) = self.location().map(Comments::from_location) {
689 comments.append_with_indent(self.depth, self.buf);
690 }
691 }
692 }
693
694 fn append_enum(&mut self, desc: EnumDescriptorProto) {
695 debug!(" enum: {:?}", desc.name());
696
697 let proto_enum_name = desc.name();
698 let enum_name = to_upper_camel(proto_enum_name);
699
700 let enum_values = &desc.value;
701 let fq_proto_enum_name = self.fq_name(proto_enum_name);
702
703 if self
704 .context
705 .resolve_extern_ident(&fq_proto_enum_name)
706 .is_some()
707 {
708 return;
709 }
710
711 self.append_doc(&fq_proto_enum_name, None);
712 self.append_type_attributes(&fq_proto_enum_name);
713 self.append_enum_attributes(&fq_proto_enum_name);
714 self.push_indent();
715 let dbg = if self.context.should_skip_debug(&fq_proto_enum_name) {
716 ""
717 } else {
718 "Debug, "
719 };
720 self.buf.push_str(&format!(
721 "#[derive(Clone, Copy, {}PartialEq, Eq, Hash, PartialOrd, Ord, {}::Enumeration)]\n",
722 dbg,
723 self.context.prost_path(),
724 ));
725 self.push_indent();
726 self.buf.push_str("#[repr(i32)]\n");
727 self.push_indent();
728 self.buf.push_str("pub enum ");
729 self.buf.push_str(&enum_name);
730 self.buf.push_str(" {\n");
731
732 let variant_mappings =
733 build_enum_value_mappings(&enum_name, self.config().strip_enum_prefix, enum_values);
734
735 self.depth += 1;
736 self.path.push(2);
737 for variant in variant_mappings.iter() {
738 self.path.push(variant.path_idx as i32);
739
740 self.append_doc(&fq_proto_enum_name, Some(variant.proto_name));
741 self.append_field_attributes(&fq_proto_enum_name, variant.proto_name);
742 self.push_indent();
743 self.buf.push_str(&variant.generated_variant_name);
744 self.buf.push_str(" = ");
745 self.buf.push_str(&variant.proto_number.to_string());
746 self.buf.push_str(",\n");
747
748 self.path.pop();
749 }
750
751 self.path.pop();
752 self.depth -= 1;
753
754 self.push_indent();
755 self.buf.push_str("}\n");
756
757 self.push_indent();
758 self.buf.push_str("impl ");
759 self.buf.push_str(&enum_name);
760 self.buf.push_str(" {\n");
761 self.depth += 1;
762 self.path.push(2);
763
764 self.push_indent();
765 self.buf.push_str(
766 "/// String value of the enum field names used in the ProtoBuf definition.\n",
767 );
768 self.push_indent();
769 self.buf.push_str("///\n");
770 self.push_indent();
771 self.buf.push_str(
772 "/// The values are not transformed in any way and thus are considered stable\n",
773 );
774 self.push_indent();
775 self.buf.push_str(
776 "/// (if the ProtoBuf definition does not change) and safe for programmatic use.\n",
777 );
778 self.push_indent();
779 self.buf
780 .push_str("pub fn as_str_name(&self) -> &'static str {\n");
781 self.depth += 1;
782
783 self.push_indent();
784 self.buf.push_str("match self {\n");
785 self.depth += 1;
786
787 for variant in variant_mappings.iter() {
788 self.push_indent();
789 self.buf.push_str("Self::");
790 self.buf.push_str(&variant.generated_variant_name);
791 self.buf.push_str(" => \"");
792 self.buf.push_str(variant.proto_name);
793 self.buf.push_str("\",\n");
794 }
795
796 self.depth -= 1;
797 self.push_indent();
798 self.buf.push_str("}\n"); self.depth -= 1;
801 self.push_indent();
802 self.buf.push_str("}\n"); self.push_indent();
805 self.buf
806 .push_str("/// Creates an enum from field names used in the ProtoBuf definition.\n");
807
808 self.push_indent();
809 self.buf
810 .push_str("pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {\n");
811 self.depth += 1;
812
813 self.push_indent();
814 self.buf.push_str("match value {\n");
815 self.depth += 1;
816
817 for variant in variant_mappings.iter() {
818 self.push_indent();
819 self.buf.push('\"');
820 self.buf.push_str(variant.proto_name);
821 self.buf.push_str("\" => Some(Self::");
822 self.buf.push_str(&variant.generated_variant_name);
823 self.buf.push_str("),\n");
824 }
825 self.push_indent();
826 self.buf.push_str("_ => None,\n");
827
828 self.depth -= 1;
829 self.push_indent();
830 self.buf.push_str("}\n"); self.depth -= 1;
833 self.push_indent();
834 self.buf.push_str("}\n"); self.path.pop();
837 self.depth -= 1;
838 self.push_indent();
839 self.buf.push_str("}\n"); }
841
842 fn push_service(&mut self, service: ServiceDescriptorProto) {
843 let name = service.name().to_owned();
844 debug!(" service: {:?}", name);
845
846 let comments = self
847 .location()
848 .map(Comments::from_location)
849 .unwrap_or_default();
850
851 self.path.push(2);
852 let methods = service
853 .method
854 .into_iter()
855 .enumerate()
856 .map(|(idx, mut method)| {
857 debug!(" method: {:?}", method.name());
858
859 self.path.push(idx as i32);
860 let comments = self
861 .location()
862 .map(Comments::from_location)
863 .unwrap_or_default();
864 self.path.pop();
865
866 let name = method.name.take().unwrap();
867 let input_proto_type = method.input_type.take().unwrap();
868 let output_proto_type = method.output_type.take().unwrap();
869 let input_type = self.resolve_ident(&input_proto_type);
870 let output_type = self.resolve_ident(&output_proto_type);
871 let client_streaming = method.client_streaming();
872 let server_streaming = method.server_streaming();
873
874 Method {
875 name: to_snake(&name),
876 proto_name: name,
877 comments,
878 input_type,
879 output_type,
880 input_proto_type,
881 output_proto_type,
882 options: method.options.unwrap_or_default(),
883 client_streaming,
884 server_streaming,
885 }
886 })
887 .collect();
888 self.path.pop();
889
890 let service = Service {
891 name: to_upper_camel(&name),
892 proto_name: name,
893 package: self.package.clone(),
894 comments,
895 methods,
896 options: service.options.unwrap_or_default(),
897 };
898
899 if let Some(service_generator) = self.context.service_generator_mut() {
900 service_generator.generate(service, self.buf)
901 }
902 }
903
904 fn push_indent(&mut self) {
905 push_indent(self.buf, self.depth);
906 }
907
908 fn push_mod(&mut self, module: &str) {
909 self.push_indent();
910 self.buf.push_str("/// Nested message and enum types in `");
911 self.buf.push_str(module);
912 self.buf.push_str("`.\n");
913
914 self.push_indent();
915 self.buf.push_str("pub mod ");
916 self.buf.push_str(&to_snake(module));
917 self.buf.push_str(" {\n");
918
919 self.type_path.push(module.into());
920
921 self.depth += 1;
922 }
923
924 fn pop_mod(&mut self) {
925 self.depth -= 1;
926
927 self.type_path.pop();
928
929 self.push_indent();
930 self.buf.push_str("}\n");
931 }
932
933 fn resolve_type(&self, field: &FieldDescriptorProto, fq_message_name: &str) -> String {
934 match field.r#type() {
935 Type::Float => String::from("f32"),
936 Type::Double => String::from("f64"),
937 Type::Uint32 | Type::Fixed32 => String::from("u32"),
938 Type::Uint64 | Type::Fixed64 => String::from("u64"),
939 Type::Int32 | Type::Sfixed32 | Type::Sint32 | Type::Enum => String::from("i32"),
940 Type::Int64 | Type::Sfixed64 | Type::Sint64 => String::from("i64"),
941 Type::Bool => String::from("bool"),
942 Type::String => format!("{}::alloc::string::String", self.context.prost_path()),
943 Type::Bytes => self
944 .context
945 .bytes_type(fq_message_name, field.name())
946 .rust_type()
947 .to_owned(),
948 Type::Group | Type::Message => self.resolve_ident(field.type_name()),
949 }
950 }
951
952 fn resolve_ident(&self, pb_ident: &str) -> String {
953 assert_eq!(".", &pb_ident[..1]);
955
956 if let Some(proto_ident) = self.context.resolve_extern_ident(pb_ident) {
957 return proto_ident;
958 }
959
960 let mut local_path = self
961 .package
962 .split('.')
963 .chain(self.type_path.iter().map(String::as_str))
964 .peekable();
965
966 if local_path.peek().is_some_and(|s| s.is_empty()) {
970 local_path.next();
971 }
972
973 let mut ident_path = pb_ident[1..].split('.');
974 let ident_type = ident_path.next_back().unwrap();
975 let mut ident_path = ident_path.peekable();
976
977 while local_path.peek().is_some() && local_path.peek() == ident_path.peek() {
979 local_path.next();
980 ident_path.next();
981 }
982
983 local_path
984 .map(|_| "super".to_string())
985 .chain(ident_path.map(to_snake))
986 .chain(iter::once(to_upper_camel(ident_type)))
987 .join("::")
988 }
989
990 fn field_type_tag(&self, field: &FieldDescriptorProto) -> Cow<'static, str> {
991 match field.r#type() {
992 Type::Float => Cow::Borrowed("float"),
993 Type::Double => Cow::Borrowed("double"),
994 Type::Int32 => Cow::Borrowed("int32"),
995 Type::Int64 => Cow::Borrowed("int64"),
996 Type::Uint32 => Cow::Borrowed("uint32"),
997 Type::Uint64 => Cow::Borrowed("uint64"),
998 Type::Sint32 => Cow::Borrowed("sint32"),
999 Type::Sint64 => Cow::Borrowed("sint64"),
1000 Type::Fixed32 => Cow::Borrowed("fixed32"),
1001 Type::Fixed64 => Cow::Borrowed("fixed64"),
1002 Type::Sfixed32 => Cow::Borrowed("sfixed32"),
1003 Type::Sfixed64 => Cow::Borrowed("sfixed64"),
1004 Type::Bool => Cow::Borrowed("bool"),
1005 Type::String => Cow::Borrowed("string"),
1006 Type::Bytes => Cow::Borrowed("bytes"),
1007 Type::Group => Cow::Borrowed("group"),
1008 Type::Message => Cow::Borrowed("message"),
1009 Type::Enum => Cow::Owned(format!(
1010 "enumeration={:?}",
1011 self.resolve_ident(field.type_name())
1012 )),
1013 }
1014 }
1015
1016 fn map_value_type_tag(&self, field: &FieldDescriptorProto) -> Cow<'static, str> {
1017 match field.r#type() {
1018 Type::Enum => Cow::Owned(format!(
1019 "enumeration({})",
1020 self.resolve_ident(field.type_name())
1021 )),
1022 _ => self.field_type_tag(field),
1023 }
1024 }
1025
1026 fn optional(&self, field: &FieldDescriptorProto) -> bool {
1027 if field.proto3_optional.unwrap_or(false) {
1028 return true;
1029 }
1030
1031 if field.label() != Label::Optional {
1032 return false;
1033 }
1034
1035 match field.r#type() {
1036 Type::Message => true,
1037 _ => self.syntax == Syntax::Proto2,
1038 }
1039 }
1040
1041 fn deprecated(&self, field: &FieldDescriptorProto) -> bool {
1043 field.options.as_ref().is_some_and(FieldOptions::deprecated)
1044 }
1045
1046 fn fq_name(&self, message_name: &str) -> String {
1048 format!(
1049 "{}{}{}{}.{}",
1050 if self.package.is_empty() { "" } else { "." },
1051 self.package.trim_matches('.'),
1052 if self.type_path.is_empty() { "" } else { "." },
1053 self.type_path.join("."),
1054 message_name,
1055 )
1056 }
1057}
1058
1059fn can_pack(field: &FieldDescriptorProto) -> bool {
1061 matches!(
1062 field.r#type(),
1063 Type::Float
1064 | Type::Double
1065 | Type::Int32
1066 | Type::Int64
1067 | Type::Uint32
1068 | Type::Uint64
1069 | Type::Sint32
1070 | Type::Sint64
1071 | Type::Fixed32
1072 | Type::Fixed64
1073 | Type::Sfixed32
1074 | Type::Sfixed64
1075 | Type::Bool
1076 | Type::Enum
1077 )
1078}
1079
1080struct EnumVariantMapping<'a> {
1081 path_idx: usize,
1082 proto_name: &'a str,
1083 proto_number: i32,
1084 generated_variant_name: String,
1085}
1086
1087fn build_enum_value_mappings<'a>(
1088 generated_enum_name: &str,
1089 do_strip_enum_prefix: bool,
1090 enum_values: &'a [EnumValueDescriptorProto],
1091) -> Vec<EnumVariantMapping<'a>> {
1092 let mut numbers = HashSet::new();
1093 let mut generated_names = HashMap::new();
1094 let mut mappings = Vec::new();
1095
1096 for (idx, value) in enum_values.iter().enumerate() {
1097 if !numbers.insert(value.number()) {
1100 continue;
1101 }
1102
1103 let mut generated_variant_name = to_upper_camel(value.name());
1104 if do_strip_enum_prefix {
1105 generated_variant_name =
1106 strip_enum_prefix(generated_enum_name, &generated_variant_name);
1107 }
1108
1109 if let Some(old_v) = generated_names.insert(generated_variant_name.to_owned(), value.name())
1110 {
1111 panic!("Generated enum variant names overlap: `{}` variant name to be used both by `{}` and `{}` ProtoBuf enum values",
1112 generated_variant_name, old_v, value.name());
1113 }
1114
1115 mappings.push(EnumVariantMapping {
1116 path_idx: idx,
1117 proto_name: value.name(),
1118 proto_number: value.number(),
1119 generated_variant_name,
1120 })
1121 }
1122 mappings
1123}