protobuf/reflect/message/
mod.rs

1use std::fmt;
2use std::io::Read;
3
4use crate::descriptor::DescriptorProto;
5use crate::descriptor::FileDescriptorProto;
6use crate::message_dyn::MessageDyn;
7use crate::message_full::MessageFull;
8use crate::reflect::dynamic::DynamicMessage;
9use crate::reflect::file::index::MessageIndices;
10use crate::reflect::file::FileDescriptorImpl;
11use crate::reflect::message::generated::GeneratedMessageDescriptor;
12use crate::reflect::reflect_eq::ReflectEq;
13use crate::reflect::reflect_eq::ReflectEqMode;
14use crate::reflect::EnumDescriptor;
15use crate::reflect::FieldDescriptor;
16use crate::reflect::FileDescriptor;
17use crate::reflect::OneofDescriptor;
18use crate::CodedInputStream;
19
20pub(crate) mod generated;
21pub(crate) mod is_initialized_is_always_true;
22pub(crate) mod message_ref;
23
24/// Dynamic representation of message type.
25///
26/// Used for reflection.
27#[derive(Clone, Eq, PartialEq, Hash)]
28pub struct MessageDescriptor {
29    pub(crate) file_descriptor: FileDescriptor,
30    pub(crate) index: usize,
31}
32
33impl fmt::Display for MessageDescriptor {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        write!(f, "{}", self.full_name())
36    }
37}
38
39impl fmt::Debug for MessageDescriptor {
40    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41        f.debug_struct("MessageDescriptor").finish_non_exhaustive()
42    }
43}
44
45impl MessageDescriptor {
46    pub(crate) fn new(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
47        MessageDescriptor {
48            file_descriptor,
49            index,
50        }
51    }
52
53    /// Get underlying `DescriptorProto` object.
54    pub fn proto(&self) -> &DescriptorProto {
55        self.file_descriptor.message_proto_by_index(self.index)
56    }
57
58    /// Message name as specified in `.proto` file.
59    pub fn name(&self) -> &str {
60        self.proto().name()
61    }
62
63    fn index_entry(&self) -> &MessageIndices {
64        self.file_descriptor.message_indices(self.index)
65    }
66
67    /// Get a message descriptor for given message type
68    pub fn for_type<M: MessageFull>() -> MessageDescriptor {
69        M::descriptor()
70    }
71
72    /// Messages declared in this messages.
73    pub fn nested_messages(&self) -> impl Iterator<Item = MessageDescriptor> + '_ {
74        self.index_entry()
75            .nested_messages
76            .iter()
77            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), *i))
78    }
79
80    /// Get enums declared in this message.
81    pub fn nested_enums(&self) -> impl Iterator<Item = EnumDescriptor> + '_ {
82        self.index_entry()
83            .nested_enums
84            .clone()
85            .map(|i| EnumDescriptor::new(self.file_descriptor.clone(), i))
86    }
87
88    /// Get a message containing this message, or `None` if this message is declared at file level.
89    pub fn enclosing_message(&self) -> Option<MessageDescriptor> {
90        self.index_entry()
91            .enclosing_message
92            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), i))
93    }
94
95    pub(crate) fn get_impl(&self) -> MessageDescriptorImplRef {
96        match &self.file_descriptor.imp {
97            FileDescriptorImpl::Generated(g) => {
98                MessageDescriptorImplRef::Generated(&g.messages[self.index])
99            }
100            FileDescriptorImpl::Dynamic(..) => MessageDescriptorImplRef::Dynamic,
101        }
102    }
103
104    /// [`FileDescriptor`] containing this message.
105    pub fn file_descriptor(&self) -> &FileDescriptor {
106        &self.file_descriptor
107    }
108
109    /// `FileDescriptorProto` containg this message type
110    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
111        self.file_descriptor().proto()
112    }
113
114    /// This message descriptor is a map entry.
115    pub fn is_map_entry(&self) -> bool {
116        self.index().map_entry
117    }
118
119    fn assert_not_map_entry(&self) {
120        assert!(
121            !self.is_map_entry(),
122            "message is map entry: {}",
123            self.full_name()
124        );
125    }
126
127    /// Message is considered always initialized.
128    #[doc(hidden)]
129    pub fn is_initialized_is_always_true(&self) -> bool {
130        self.index().is_initialized_is_always_true
131    }
132
133    /// New empty message.
134    ///
135    /// # Panics
136    ///
137    /// If this message is a map entry message.
138    pub fn new_instance(&self) -> Box<dyn MessageDyn> {
139        self.assert_not_map_entry();
140        match self.get_impl() {
141            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.new_instance(),
142            MessageDescriptorImplRef::Dynamic => Box::new(DynamicMessage::new(self.clone())),
143        }
144    }
145
146    /// Shared immutable empty message.
147    ///
148    /// Returns `None` for dynamic message.
149    ///
150    /// # Panics
151    ///
152    /// If this message is a map entry message.
153    pub fn default_instance(&self) -> Option<&'static dyn MessageDyn> {
154        self.assert_not_map_entry();
155        match self.get_impl() {
156            MessageDescriptorImplRef::Generated(g) => Some(g.non_map().factory.default_instance()),
157            MessageDescriptorImplRef::Dynamic => None,
158        }
159    }
160
161    /// Clone a message
162    pub(crate) fn clone_message(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn> {
163        assert!(&message.descriptor_dyn() == self);
164        match self.get_impl() {
165            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.clone(message),
166            MessageDescriptorImplRef::Dynamic => {
167                let message: &DynamicMessage = DynamicMessage::downcast_ref(message);
168                Box::new(message.clone())
169            }
170        }
171    }
172
173    /// Check if two messages equal.
174    ///
175    /// # Panics
176    ///
177    /// Is any message has different type than this descriptor.
178    pub fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool {
179        match self.get_impl() {
180            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.eq(a, b),
181            MessageDescriptorImplRef::Dynamic => unimplemented!(),
182        }
183    }
184
185    /// Similar to `eq`, but considers `NaN` values equal.
186    ///
187    /// # Panics
188    ///
189    /// Is any message has different type than this descriptor.
190    pub(crate) fn reflect_eq(
191        &self,
192        a: &dyn MessageDyn,
193        b: &dyn MessageDyn,
194        mode: &ReflectEqMode,
195    ) -> bool {
196        // Explicitly force panic even if field list is empty
197        assert_eq!(self, &a.descriptor_dyn());
198        assert_eq!(self, &b.descriptor_dyn());
199
200        for field in self.fields() {
201            let af = field.get_reflect(a);
202            let bf = field.get_reflect(b);
203            if !af.reflect_eq(&bf, mode) {
204                return false;
205            }
206        }
207        true
208    }
209
210    pub(crate) fn reflect_eq_maybe_unrelated(
211        a: &dyn MessageDyn,
212        b: &dyn MessageDyn,
213        mode: &ReflectEqMode,
214    ) -> bool {
215        let ad = a.descriptor_dyn();
216        let bd = b.descriptor_dyn();
217        ad == bd && ad.reflect_eq(a, b, mode)
218    }
219
220    /// Fully qualified protobuf message name
221    pub fn full_name(&self) -> &str {
222        &self.index_entry().full_name
223    }
224
225    /// Name relative to the package where the message is declared.
226    pub fn name_to_package(&self) -> &str {
227        &self.index_entry().name_to_package
228    }
229
230    /// Nested oneofs including synthetic.
231    pub fn all_oneofs<'a>(&'a self) -> impl Iterator<Item = OneofDescriptor> + 'a {
232        self.index_entry()
233            .oneofs
234            .clone()
235            .map(move |i| OneofDescriptor {
236                file_descriptor: self.file_descriptor.clone(),
237                index: i,
238            })
239    }
240
241    /// Non-synthetic oneofs.
242    pub fn oneofs<'a>(&'a self) -> impl Iterator<Item = OneofDescriptor> + 'a {
243        self.all_oneofs().filter(|oneof| !oneof.is_synthetic())
244    }
245
246    /// Get message oneof by name (**not implemented**).
247    pub fn oneof_by_name(&self, name: &str) -> Option<OneofDescriptor> {
248        self.all_oneofs().find(|oneof| oneof.name() == name)
249    }
250
251    /// Message field descriptors.
252    pub fn fields<'a>(&'a self) -> impl Iterator<Item = FieldDescriptor> + 'a {
253        self.index()
254            .message_index
255            .regular_field_range()
256            .map(move |index| FieldDescriptor {
257                file_descriptor: self.file_descriptor.clone(),
258                index,
259            })
260    }
261
262    /// Extension fields.
263    pub fn extensions(&self) -> impl Iterator<Item = FieldDescriptor> + '_ {
264        self.index()
265            .message_index
266            .extension_field_range()
267            .map(move |index| FieldDescriptor {
268                file_descriptor: self.file_descriptor.clone(),
269                index,
270            })
271    }
272
273    pub(crate) fn index(&self) -> &MessageIndices {
274        &self.file_descriptor.common().messages[self.index]
275    }
276
277    pub(crate) fn field_by_index(&self, index: usize) -> FieldDescriptor {
278        FieldDescriptor {
279            file_descriptor: self.file_descriptor.clone(),
280            index: self.index().message_index.first_field_index + index,
281        }
282    }
283
284    /// Find message field by protobuf field name
285    ///
286    /// Note: protobuf field name might be different for Rust field name.
287    // TODO: return value, not pointer, pointer is not compatible with dynamic message
288    pub fn field_by_name(&self, name: &str) -> Option<FieldDescriptor> {
289        let &index = self.index().message_index.field_index_by_name.get(name)?;
290        Some(self.field_by_index(index))
291    }
292
293    /// Find message field by field name or field JSON name
294    pub fn field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
295        let &index = self
296            .index()
297            .message_index
298            .field_index_by_name_or_json_name
299            .get(name)?;
300        Some(self.field_by_index(index))
301    }
302
303    /// Find message field by field name
304    pub fn field_by_number(&self, number: u32) -> Option<FieldDescriptor> {
305        let &index = self
306            .index()
307            .message_index
308            .field_index_by_number
309            .get(&number)?;
310        Some(self.field_by_index(index))
311    }
312
313    /// Parse message from stream.
314    pub fn parse_from(&self, is: &mut CodedInputStream) -> crate::Result<Box<dyn MessageDyn>> {
315        let mut r = self.new_instance();
316        r.merge_from_dyn(is)?;
317        r.check_initialized_dyn()?;
318        Ok(r)
319    }
320
321    /// Parse message from reader.
322    /// Parse stops on EOF or when error encountered.
323    pub fn parse_from_reader(&self, reader: &mut dyn Read) -> crate::Result<Box<dyn MessageDyn>> {
324        let mut is = CodedInputStream::new(reader);
325        let r = self.parse_from(&mut is)?;
326        is.check_eof()?;
327        Ok(r)
328    }
329
330    /// Parse message from byte array.
331    pub fn parse_from_bytes(&self, bytes: &[u8]) -> crate::Result<Box<dyn MessageDyn>> {
332        let mut is = CodedInputStream::from_bytes(bytes);
333        let r = self.parse_from(&mut is)?;
334        is.check_eof()?;
335        Ok(r)
336    }
337}
338
339pub(crate) enum MessageDescriptorImplRef {
340    Generated(&'static GeneratedMessageDescriptor),
341    Dynamic,
342}
343
344#[cfg(test)]
345mod test {
346    use crate::descriptor::descriptor_proto::ExtensionRange;
347    use crate::descriptor::field_descriptor_proto::Type;
348    use crate::descriptor::DescriptorProto;
349    use crate::descriptor::FieldDescriptorProto;
350    use crate::EnumFull;
351    use crate::MessageFull;
352
353    #[test]
354    #[cfg_attr(miri, ignore)] // Too slow on Miri.
355    fn nested_messages() {
356        assert!(DescriptorProto::descriptor()
357            .nested_messages()
358            .collect::<Vec<_>>()
359            .contains(&ExtensionRange::descriptor()));
360    }
361
362    #[test]
363    #[cfg_attr(miri, ignore)] // Too slow on Miri.
364    fn nested_enums() {
365        assert!(FieldDescriptorProto::descriptor()
366            .nested_enums()
367            .collect::<Vec<_>>()
368            .contains(&Type::enum_descriptor()));
369    }
370
371    #[test]
372    #[cfg_attr(miri, ignore)] // Too slow on Miri.
373    fn enclosing_message() {
374        assert_eq!(
375            Some(DescriptorProto::descriptor()),
376            ExtensionRange::descriptor().enclosing_message()
377        );
378        assert_eq!(None, DescriptorProto::descriptor().enclosing_message());
379    }
380}