prost_build/
code_generator.rs

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
28/// State object for the code generation process on a single input file.
29pub 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        // Skip external types.
155        if self
156            .context
157            .resolve_extern_ident(&fq_message_name)
158            .is_some()
159        {
160            return;
161        }
162
163        // Split the nested message types into a vector of normal nested message types, and a map
164        // of the map field entry types. The path index of the nested message types is preserved so
165        // that comments can be retrieved.
166        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        // Split the fields into a vector of the normal fields, and oneof fields.
192        // Path indexes are preserved so that comments can be retrieved.
193        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        // Optional fields create a synthetic oneof that we want to skip
209        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                    // Field types are fully qualified, so we extract
467                    // the last segment and strip it from the left
468                    // side of the default value.
469                    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"); // End of match
799
800        self.depth -= 1;
801        self.push_indent();
802        self.buf.push_str("}\n"); // End of as_str_name()
803
804        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"); // End of match
831
832        self.depth -= 1;
833        self.push_indent();
834        self.buf.push_str("}\n"); // End of from_str_name()
835
836        self.path.pop();
837        self.depth -= 1;
838        self.push_indent();
839        self.buf.push_str("}\n"); // End of impl
840    }
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        // protoc should always give fully qualified identifiers.
954        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 no package is specified the start of the package name will be '.'
967        // and split will return an empty string ("") which breaks resolution
968        // The fix to this is to ignore the first item if it is empty.
969        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        // Skip path elements in common.
978        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    /// Returns `true` if the field options includes the `deprecated` option.
1042    fn deprecated(&self, field: &FieldDescriptorProto) -> bool {
1043        field.options.as_ref().is_some_and(FieldOptions::deprecated)
1044    }
1045
1046    /// Returns the fully-qualified name, starting with a dot
1047    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
1059/// Returns `true` if the repeated field type can be packed.
1060fn 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        // Skip duplicate enum values. Protobuf allows this when the
1098        // 'allow_alias' option is set.
1099        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}