prost_wkt/
lib.rs

1pub use inventory;
2
3pub use typetag;
4
5/// Trait to support serialization and deserialization of `prost` messages.
6#[typetag::serde(tag = "@type")]
7pub trait MessageSerde: prost::Message + std::any::Any {
8    /// message name as in proto file
9    fn message_name(&self) -> &'static str;
10    /// package name as in proto file
11    fn package_name(&self) -> &'static str;
12    /// the message proto type url e.g. type.googleapis.com/my.package.MyMessage
13    fn type_url(&self) -> &'static str;
14    /// Creates a new instance of this message using the protobuf encoded data
15    fn new_instance(&self, data: Vec<u8>) -> Result<Box<dyn MessageSerde>, prost::DecodeError>;
16    /// Returns the encoded protobuf message as bytes
17    fn try_encoded(&self) -> Result<Vec<u8>, prost::EncodeError>;
18}
19
20/// The implementation here is a direct copy of the `impl dyn` of [`std::any::Any`]!
21impl dyn MessageSerde {
22    /// Returns `true` if the inner type is the same as `T`.
23    #[inline]
24    pub fn is<T: MessageSerde>(&self) -> bool {
25        // Get `TypeId` of the type this function is instantiated with.
26        let t = std::any::TypeId::of::<T>();
27
28        // Get `TypeId` of the type in the trait object (`self`).
29        let concrete = self.type_id();
30
31        // Compare both `TypeId`s on equality.
32        t == concrete
33    }
34
35    /// Returns some reference to the inner value if it is of type `T`, or
36    /// `None` if it isn't.
37    #[inline]
38    pub fn downcast_ref<T: MessageSerde>(&self) -> Option<&T> {
39        if self.is::<T>() {
40            // SAFETY: just checked whether we are pointing to the correct type, and we can rely on
41            // that check for memory safety because we have implemented Any for all types; no other
42            // impls can exist as they would conflict with our impl.
43            unsafe { Some(self.downcast_ref_unchecked()) }
44        } else {
45            Option::None
46        }
47    }
48
49    /// Returns some mutable reference to the boxed value if it is of type `T`,
50    /// or `None` if it isn't.
51    #[inline]
52    pub fn downcast_mut<T: MessageSerde>(&mut self) -> Option<&mut T> {
53        if self.is::<T>() {
54            // SAFETY: just checked whether we are pointing to the correct type, and we can rely on
55            // that check for memory safety because we have implemented Any for all types; no other
56            // impls can exist as they would conflict with our impl.
57            unsafe { Some(self.downcast_mut_unchecked()) }
58        } else {
59            Option::None
60        }
61    }
62
63    /// Returns a reference to the inner value as type `dyn T`.
64    ///
65    /// # Safety
66    ///
67    /// The contained value must be of type `T`. Calling this method
68    /// with the incorrect type is *undefined behavior*.
69    #[inline]
70    pub unsafe fn downcast_ref_unchecked<T: MessageSerde>(&self) -> &T {
71        debug_assert!(self.is::<T>());
72        // SAFETY: caller guarantees that T is the correct type
73        unsafe { &*(self as *const dyn MessageSerde as *const T) }
74    }
75
76    /// Returns a mutable reference to the inner value as type `dyn T`.
77    ///
78    /// # Safety
79    ///
80    /// The contained value must be of type `T`. Calling this method
81    /// with the incorrect type is *undefined behavior*.
82    #[inline]
83    pub unsafe fn downcast_mut_unchecked<T: MessageSerde>(&mut self) -> &mut T {
84        &mut *(self as *mut Self as *mut T)
85    }
86}
87
88type MessageSerdeDecoderFn = fn(&[u8]) -> Result<Box<dyn MessageSerde>, ::prost::DecodeError>;
89
90pub struct MessageSerdeDecoderEntry {
91    pub type_url: &'static str,
92    pub decoder: MessageSerdeDecoderFn,
93}
94
95inventory::collect!(MessageSerdeDecoderEntry);