protobuf/
message_dyn.rs

1use std::any::Any;
2use std::any::TypeId;
3use std::fmt;
4use std::io::Write;
5
6use crate::coded_output_stream::with::WithCodedOutputStream;
7use crate::error::ProtobufError;
8use crate::reflect::MessageDescriptor;
9use crate::reflect::ReflectEqMode;
10use crate::wire_format::check_message_size;
11use crate::CodedInputStream;
12use crate::CodedOutputStream;
13use crate::MessageFull;
14use crate::SpecialFields;
15use crate::UnknownFields;
16
17/// Dynamic-dispatch version of either generated message or dynamic message.
18///
19/// Generated messages implement [`MessageFull`](crate::MessageFull) unless lite runtime requested.
20/// Dynamic messages can be created with
21/// [`FileDescriptor::new_dynamic`](crate::reflect::FileDescriptor::new_dynamic).
22pub trait MessageDyn: Any + fmt::Debug + fmt::Display + Send + Sync + 'static {
23    /// Message descriptor for this message, used for reflection.
24    fn descriptor_dyn(&self) -> MessageDescriptor;
25
26    /// Update this message fields with contents of given stream.
27    fn merge_from_dyn(&mut self, is: &mut CodedInputStream) -> crate::Result<()>;
28
29    /// Write the message.
30    fn write_to_with_cached_sizes_dyn(&self, os: &mut CodedOutputStream) -> crate::Result<()>;
31
32    /// Compute (and cache) the message size.
33    fn compute_size_dyn(&self) -> u64;
34
35    /// True iff all required fields are initialized.
36    /// Always returns `true` for protobuf 3.
37    fn is_initialized_dyn(&self) -> bool;
38
39    /// Get a reference to special fields.
40    fn special_fields_dyn(&self) -> &SpecialFields;
41    /// Get a mutable reference to special fields.
42    fn mut_special_fields_dyn(&mut self) -> &mut SpecialFields;
43}
44
45impl<M: MessageFull> MessageDyn for M {
46    fn descriptor_dyn(&self) -> MessageDescriptor {
47        M::descriptor()
48    }
49
50    fn merge_from_dyn(&mut self, is: &mut CodedInputStream) -> crate::Result<()> {
51        self.merge_from(is)
52    }
53
54    fn write_to_with_cached_sizes_dyn(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
55        self.write_to_with_cached_sizes(os)
56    }
57
58    fn compute_size_dyn(&self) -> u64 {
59        self.compute_size()
60    }
61
62    fn is_initialized_dyn(&self) -> bool {
63        self.is_initialized()
64    }
65
66    fn special_fields_dyn(&self) -> &SpecialFields {
67        self.special_fields()
68    }
69
70    fn mut_special_fields_dyn(&mut self) -> &mut SpecialFields {
71        self.mut_special_fields()
72    }
73}
74
75impl dyn MessageDyn {
76    /// Check if all required fields of this object are initialized.
77    pub fn check_initialized_dyn(&self) -> crate::Result<()> {
78        if !self.is_initialized_dyn() {
79            Err(
80                ProtobufError::MessageNotInitialized(self.descriptor_dyn().name().to_owned())
81                    .into(),
82            )
83        } else {
84            Ok(())
85        }
86    }
87
88    /// Write the message to the writer.
89    pub fn write_to_writer_dyn(&self, w: &mut dyn Write) -> crate::Result<()> {
90        w.with_coded_output_stream(|os| self.write_to_dyn(os))
91    }
92
93    /// Write the message to bytes vec.
94    pub fn write_to_vec_dyn(&self, v: &mut Vec<u8>) -> crate::Result<()> {
95        v.with_coded_output_stream(|os| self.write_to_dyn(os))
96    }
97
98    /// Write the message to the stream.
99    ///
100    /// Results in error if message is not fully initialized.
101    pub fn write_to_dyn(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
102        self.check_initialized_dyn()?;
103
104        // cache sizes
105        let size = self.compute_size_dyn();
106        let size = check_message_size(size)?;
107        os.reserve_additional(size, self.descriptor_dyn().name())?;
108        self.write_to_with_cached_sizes_dyn(os)?;
109
110        Ok(())
111    }
112
113    /// Write the message to the vec, prepend the message with message length
114    /// encoded as varint.
115    pub fn write_length_delimited_to_vec_dyn(&self, vec: &mut Vec<u8>) -> crate::Result<()> {
116        let mut os = CodedOutputStream::vec(vec);
117        self.write_length_delimited_to_dyn(&mut os)?;
118        os.flush()?;
119        Ok(())
120    }
121
122    /// Update this message object with fields read from given stream.
123    pub fn merge_from_bytes_dyn(&mut self, bytes: &[u8]) -> crate::Result<()> {
124        let mut is = CodedInputStream::from_bytes(bytes);
125        self.merge_from_dyn(&mut is)
126    }
127
128    /// Write the message to bytes vec.
129    ///
130    /// > **Note**: You can use [`Message::parse_from_bytes`](crate::Message::parse_from_bytes)
131    /// to do the reverse.
132    pub fn write_to_bytes_dyn(&self) -> crate::Result<Vec<u8>> {
133        self.check_initialized_dyn()?;
134
135        let size = self.compute_size_dyn();
136        let size = check_message_size(size)?;
137        let mut v = Vec::new();
138        let mut os = CodedOutputStream::vec(&mut v);
139        os.reserve_additional(size, self.descriptor_dyn().name())?;
140        self.write_to_with_cached_sizes_dyn(&mut os)?;
141        os.flush()?;
142        drop(os);
143        Ok(v)
144    }
145
146    /// Write the message to the stream prepending the message with message length
147    /// encoded as varint.
148    pub fn write_length_delimited_to_dyn(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
149        let size = self.compute_size_dyn();
150        let size = check_message_size(size)?;
151        os.reserve_additional_for_length_delimited(size, self.descriptor_dyn().name())?;
152        os.write_raw_varint32(size)?;
153
154        let pos = os.total_bytes_written();
155
156        self.write_to_with_cached_sizes_dyn(os)?;
157
158        // Cheap self-check.
159        assert_eq!(os.total_bytes_written() - pos, size as u64);
160
161        Ok(())
162    }
163
164    /// Write the message to the writer, prepend the message with message length
165    /// encoded as varint.
166    pub fn write_length_delimited_to_writer_dyn(&self, w: &mut dyn Write) -> crate::Result<()> {
167        w.with_coded_output_stream(|os| self.write_length_delimited_to_dyn(os))
168    }
169
170    /// Write the message to the bytes vec, prepend the message with message length
171    /// encoded as varint.
172    pub fn write_length_delimited_to_bytes_dyn(&self) -> crate::Result<Vec<u8>> {
173        let mut v = Vec::new();
174        v.with_coded_output_stream(|os| self.write_length_delimited_to_dyn(os))?;
175        Ok(v)
176    }
177
178    /// Get a reference to unknown fields.
179    pub fn unknown_fields_dyn(&self) -> &UnknownFields {
180        self.special_fields_dyn().unknown_fields()
181    }
182    /// Get a mutable reference to unknown fields.
183    pub fn mut_unknown_fields_dyn(&mut self) -> &mut UnknownFields {
184        self.mut_special_fields_dyn().mut_unknown_fields()
185    }
186
187    /// Downcast `Box<dyn Message>` to specific message type.
188    ///
189    /// ```
190    /// # use protobuf::{MessageFull, MessageDyn};
191    /// # fn foo<MyMessage: MessageFull>(message: Box<dyn MessageDyn>) {
192    /// let m: Box<dyn MessageDyn> = message;
193    /// let m: Box<MyMessage> = <dyn MessageDyn>::downcast_box(m).unwrap();
194    /// # }
195    /// ```
196    pub fn downcast_box<T: Any>(
197        self: Box<dyn MessageDyn>,
198    ) -> std::result::Result<Box<T>, Box<dyn MessageDyn>> {
199        if Any::type_id(&*self) == TypeId::of::<T>() {
200            unsafe {
201                let raw: *mut dyn MessageDyn = Box::into_raw(self);
202                Ok(Box::from_raw(raw as *mut T))
203            }
204        } else {
205            Err(self)
206        }
207    }
208
209    /// Downcast `&dyn Message` to specific message type.
210    ///
211    /// ```
212    /// # use protobuf::{MessageFull, MessageDyn};
213    /// # fn foo<MyMessage: MessageFull>(message: &dyn MessageDyn) {
214    /// let m: &dyn MessageDyn = message;
215    /// let m: &MyMessage = <dyn MessageDyn>::downcast_ref(m).unwrap();
216    /// # }
217    /// ```
218    pub fn downcast_ref<'a, M: MessageFull + 'a>(&'a self) -> Option<&'a M> {
219        if Any::type_id(&*self) == TypeId::of::<M>() {
220            unsafe { Some(&*(self as *const dyn MessageDyn as *const M)) }
221        } else {
222            None
223        }
224    }
225
226    /// Downcast `&mut dyn Message` to specific message type.
227    ///
228    /// ```
229    /// # use protobuf::{MessageFull, MessageDyn};
230    /// # fn foo<MyMessage: MessageFull>(message: &mut dyn MessageDyn) {
231    /// let m: &mut dyn MessageDyn = message;
232    /// let m: &mut MyMessage = <dyn MessageDyn>::downcast_mut(m).unwrap();
233    /// # }
234    /// ```
235    pub fn downcast_mut<'a, M: MessageFull + 'a>(&'a mut self) -> Option<&'a mut M> {
236        if Any::type_id(&*self) == TypeId::of::<M>() {
237            unsafe { Some(&mut *(self as *mut dyn MessageDyn as *mut M)) }
238        } else {
239            None
240        }
241    }
242
243    /// Clone from a `dyn Message` reference.
244    pub fn clone_box(&self) -> Box<dyn MessageDyn> {
245        self.descriptor_dyn().clone_message(self)
246    }
247
248    /// Reflectively compare the messages.
249    pub fn reflect_eq_dyn(&self, other: &dyn MessageDyn, mode: &ReflectEqMode) -> bool {
250        MessageDescriptor::reflect_eq_maybe_unrelated(self, other, mode)
251    }
252}
253
254impl Clone for Box<dyn MessageDyn> {
255    fn clone(&self) -> Self {
256        (*self).clone_box()
257    }
258}
259
260impl PartialEq for Box<dyn MessageDyn> {
261    fn eq(&self, other: &Box<dyn MessageDyn>) -> bool {
262        MessageDescriptor::reflect_eq_maybe_unrelated(&**self, &**other, &ReflectEqMode::default())
263    }
264}
265
266#[cfg(test)]
267mod test {
268    use crate::descriptor::FileDescriptorProto;
269    use crate::MessageDyn;
270
271    #[test]
272    fn downcast_ref() {
273        let m = FileDescriptorProto::new();
274        let d = &m as &dyn MessageDyn;
275        let c: &FileDescriptorProto = d.downcast_ref().unwrap();
276        assert_eq!(
277            c as *const FileDescriptorProto,
278            &m as *const FileDescriptorProto
279        );
280    }
281
282    #[test]
283    fn downcast_mut() {
284        let mut m = FileDescriptorProto::new();
285        let d = &mut m as &mut dyn MessageDyn;
286        let c: &mut FileDescriptorProto = d.downcast_mut().unwrap();
287        assert_eq!(
288            c as *const FileDescriptorProto,
289            &m as *const FileDescriptorProto
290        );
291    }
292
293    #[test]
294    fn downcast_box() {
295        let m = FileDescriptorProto::new();
296        let d: Box<dyn MessageDyn> = Box::new(m);
297        let mut _c: Box<FileDescriptorProto> = d.downcast_box().unwrap();
298    }
299}