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);