protobuf/reflect/file/
generated.rs

1use std::collections::HashMap;
2use std::fmt;
3use std::fmt::Formatter;
4
5use crate::descriptor::FileDescriptorProto;
6use crate::owning_ref::OwningRef;
7use crate::reflect::enums::generated::GeneratedEnumDescriptor;
8use crate::reflect::file::index::FileDescriptorCommon;
9use crate::reflect::message::generated::GeneratedMessageDescriptor;
10use crate::reflect::oneof::generated::GeneratedOneofDescriptor;
11use crate::reflect::FileDescriptor;
12use crate::reflect::GeneratedEnumDescriptorData;
13use crate::reflect::GeneratedMessageDescriptorData;
14
15/// Reflection for objects defined in `.proto` file (messages, enums, etc).
16#[doc(hidden)]
17pub struct GeneratedFileDescriptor {
18    pub(crate) proto: &'static FileDescriptorProto,
19    pub(crate) messages: Vec<GeneratedMessageDescriptor>,
20    pub(crate) enums: Vec<GeneratedEnumDescriptor>,
21    pub(crate) oneofs: Vec<GeneratedOneofDescriptor>,
22    pub(crate) common: FileDescriptorCommon,
23}
24
25impl fmt::Debug for GeneratedFileDescriptor {
26    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
27        f.debug_struct("GeneratedFileDescriptor")
28            .field("proto.name", &self.proto.name())
29            .finish_non_exhaustive()
30    }
31}
32
33impl GeneratedFileDescriptor {
34    /// This function is called from generated code.
35    pub fn new_generated(
36        file_descriptor_proto: &'static FileDescriptorProto,
37        dependencies: Vec<FileDescriptor>,
38        messages: Vec<GeneratedMessageDescriptorData>,
39        enums: Vec<GeneratedEnumDescriptorData>,
40    ) -> GeneratedFileDescriptor {
41        let common =
42            FileDescriptorCommon::new(OwningRef::new_static(file_descriptor_proto), dependencies)
43                .unwrap();
44
45        let mut messages: HashMap<&str, GeneratedMessageDescriptorData> = messages
46            .into_iter()
47            .map(|m| (m.protobuf_name_to_package, m))
48            .collect();
49
50        let mut enums: HashMap<&str, GeneratedEnumDescriptorData> =
51            enums.into_iter().map(|e| (e.name_in_file, e)).collect();
52
53        let mut oneofs = Vec::new();
54        for oneof in &common.oneofs {
55            let message = &common.messages[oneof.containing_message];
56            let message_proto = &message.proto;
57            let oneof_proto = &message_proto.oneof_decl[oneof.index_in_containing_message];
58            let message = messages.get(message.name_to_package.as_str()).unwrap();
59            let oneof_data = &message.oneofs.iter().find(|o| o.name == oneof_proto.name());
60            if oneof.synthetic {
61                assert!(oneof_data.is_none());
62                oneofs.push(GeneratedOneofDescriptor::new_synthetic())
63            } else {
64                let oneof = GeneratedOneofDescriptor::new(oneof_data.unwrap());
65                oneofs.push(oneof);
66            }
67        }
68
69        let messages = common
70            .messages
71            .iter()
72            .map(|message_index| {
73                if message_index.proto.options.map_entry() {
74                    GeneratedMessageDescriptor::new_map_entry()
75                } else {
76                    let message = messages
77                        .remove(message_index.name_to_package.as_str())
78                        .unwrap();
79                    GeneratedMessageDescriptor::new(message, file_descriptor_proto, &common)
80                }
81            })
82            .collect();
83
84        let enums = common
85            .enums
86            .iter()
87            .map(|enum_index| {
88                let en = enums.remove(enum_index.name_to_package.as_str()).unwrap();
89                GeneratedEnumDescriptor::new(en, file_descriptor_proto)
90            })
91            .collect();
92
93        GeneratedFileDescriptor {
94            proto: file_descriptor_proto,
95            messages,
96            enums,
97            oneofs,
98            common,
99        }
100    }
101}