protobuf/reflect/message/
generated.rs

1//! Generated messages reflection support.
2
3use std::fmt;
4use std::marker;
5
6use crate::descriptor::FileDescriptorProto;
7use crate::message_dyn::MessageDyn;
8use crate::message_full::MessageFull;
9use crate::reflect::acc::FieldAccessor;
10use crate::reflect::file::index::FileDescriptorCommon;
11use crate::reflect::find_message_or_enum::find_message_or_enum;
12use crate::reflect::find_message_or_enum::MessageOrEnum;
13use crate::reflect::GeneratedOneofDescriptorData;
14
15/// Sized to dynamic reflection operations.
16pub(crate) trait MessageFactory: Send + Sync + 'static {
17    fn new_instance(&self) -> Box<dyn MessageDyn>;
18    fn default_instance(&self) -> &dyn MessageDyn;
19    fn clone(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn>;
20    fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool;
21}
22
23impl<'a> fmt::Debug for &'a dyn MessageFactory {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        f.debug_struct("MessageFactory").finish()
26    }
27}
28
29/// The only message factory implementation.
30pub(crate) struct MessageFactoryImpl<M>(pub marker::PhantomData<M>);
31
32impl<M> MessageFactory for MessageFactoryImpl<M>
33where
34    M: MessageFull,
35{
36    fn new_instance(&self) -> Box<dyn MessageDyn> {
37        let m: M = Default::default();
38        Box::new(m)
39    }
40
41    fn default_instance(&self) -> &dyn MessageDyn {
42        M::default_instance() as &dyn MessageDyn
43    }
44
45    fn clone(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn> {
46        let m: &M = message.downcast_ref().expect("wrong message type");
47        Box::new(m.clone())
48    }
49
50    fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool {
51        let a: &M = a.downcast_ref().expect("wrong message type");
52        let b: &M = b.downcast_ref().expect("wrong message type");
53        a == b
54    }
55}
56
57#[doc(hidden)]
58pub struct GeneratedMessageDescriptorData {
59    pub(crate) protobuf_name_to_package: &'static str,
60    pub(crate) fields: Vec<FieldAccessor>,
61    pub(crate) factory: &'static dyn MessageFactory,
62    pub(crate) oneofs: Vec<GeneratedOneofDescriptorData>,
63}
64
65impl GeneratedMessageDescriptorData {
66    /// Construct a new message descriptor.
67    ///
68    /// This operation is called from generated code and rarely
69    /// need to be called directly.
70    ///
71    /// This function is not a part of public API.
72    #[doc(hidden)]
73    pub fn new_2<M: MessageFull>(
74        protobuf_name_to_package: &'static str,
75        fields: Vec<FieldAccessor>,
76        oneofs: Vec<GeneratedOneofDescriptorData>,
77    ) -> GeneratedMessageDescriptorData {
78        let factory = &MessageFactoryImpl(marker::PhantomData::<M>);
79        GeneratedMessageDescriptorData {
80            protobuf_name_to_package,
81            fields,
82            factory,
83            oneofs,
84        }
85    }
86}
87
88#[derive(Debug)]
89pub(crate) struct NonMapMessageDescriptor {
90    pub(crate) factory: &'static dyn MessageFactory,
91
92    pub(crate) fields: Vec<FieldAccessor>,
93}
94
95#[derive(Debug)]
96pub(crate) struct GeneratedMessageDescriptor {
97    pub(crate) non_map: Option<NonMapMessageDescriptor>,
98}
99
100impl GeneratedMessageDescriptor {
101    pub(crate) fn new_map_entry() -> GeneratedMessageDescriptor {
102        GeneratedMessageDescriptor { non_map: None }
103    }
104
105    pub(crate) fn new(
106        data: GeneratedMessageDescriptorData,
107        file_descriptor_proto: &'static FileDescriptorProto,
108        _file_index: &FileDescriptorCommon,
109    ) -> GeneratedMessageDescriptor {
110        let GeneratedMessageDescriptorData {
111            protobuf_name_to_package,
112            fields,
113            factory,
114            oneofs: _,
115        } = data;
116
117        let (_path_to_package, _proto) =
118            match find_message_or_enum(file_descriptor_proto, protobuf_name_to_package) {
119                Some((path_to_package, MessageOrEnum::Message(m))) => (path_to_package, m),
120                Some((_, MessageOrEnum::Enum(_))) => panic!("not a message"),
121                None => panic!("not found"),
122            };
123
124        GeneratedMessageDescriptor {
125            non_map: Some(NonMapMessageDescriptor { factory, fields }),
126        }
127    }
128
129    pub(crate) fn non_map(&self) -> &NonMapMessageDescriptor {
130        match &self.non_map {
131            Some(non_map) => non_map,
132            None => panic!("map message"),
133        }
134    }
135}