strut_rabbitmq/transport/inbound/
decoder.rs

1use std::convert::Infallible;
2use std::error::Error;
3use std::string::FromUtf8Error;
4
5/// Represents a way of decoding a payload of an incoming message (which is
6/// received as a sequence of bytes) into an arbitrary result type.
7///
8/// It is important to know that both the original bytes (`Vec<u8>`) and the
9/// decoded [`Result`](Decoder::Result) will be owned by the same
10/// [`Envelope`](crate::Envelope). Given that Rust doesn’t allow
11/// self-referential structs, we have to keep in mind that the result type may
12/// not contain references to the original bytes.
13///
14/// Also, since the envelope is not easily destructed, only a reference to the
15/// decoded payload is [exposed](crate::Envelope::payload).
16///
17/// For cases, where references to the original bytes are needed in the decoded
18/// result, or where the decoded result must be owned by the external logic, the
19/// byte slice may be [accessed](crate::Envelope::bytes) on the envelope for
20/// manual decoding, and the provided [`NoopDecoder`] may be used as a dud.
21pub trait Decoder {
22    /// The type of decoded result.
23    type Result;
24
25    /// The type of error produced when decoding is not possible.
26    type Error: Error;
27
28    /// Decodes the given sequence of bytes into the desired
29    /// [`Result`](Decoder::Result), or returns an appropriate
30    /// [`Error`](Decoder::Error).
31    fn decode(&self, bytes: &[u8]) -> Result<Self::Result, Self::Error>;
32}
33
34/// Implements [`Decoder`] for any function or closure that returns a
35/// non-referential [`Result`].
36///
37/// If the result references the given `bytes`, this implementation will not
38/// work. See the [`Decoder`] documentation for more details.
39impl<F, R, E> Decoder for F
40where
41    F: Fn(&[u8]) -> Result<R, E>,
42    E: Error,
43{
44    type Result = R;
45    type Error = E;
46
47    fn decode(&self, bytes: &[u8]) -> Result<Self::Result, Self::Error> {
48        self(bytes)
49    }
50}
51
52/// In some cases it is not necessary or not desirable to decode the incoming
53/// message’s bytes on consumption. This convenience implementation of [`Decoder`]
54/// enables such cases by not doing anything and returning a unit type `()`.
55///
56/// The original, un-decoded [`bytes`](crate::Envelope::bytes) of the
57/// message are always available on the [`Envelope`](crate::Envelope).
58///
59/// See the [`Decoder`] documentation for more details.
60pub struct NoopDecoder;
61
62impl Decoder for NoopDecoder {
63    type Result = ();
64    type Error = Infallible;
65
66    fn decode(&self, _bytes: &[u8]) -> Result<Self::Result, Self::Error> {
67        Ok(())
68    }
69}
70
71/// Implements [`Decoder`] that allocates an owned UTF-8 [`String`] with a copy
72/// of the given bytes. This decoder fails with [`FromUtf8Error`] if the given
73/// bytes cannot be interpreted as valid UTF-8.
74#[derive(Default)]
75pub struct StringDecoder;
76
77impl Decoder for StringDecoder {
78    type Result = String;
79    type Error = FromUtf8Error;
80
81    fn decode(&self, bytes: &[u8]) -> Result<Self::Result, Self::Error> {
82        String::from_utf8(bytes.to_vec())
83    }
84}
85
86/// This convenience implementation of [`Decoder`] enables automatically decoding
87/// the incoming message’s bytes as a JSON into the given generic type `T`.
88///
89/// Since both the original bytes and the decoded object will be stored on the
90/// same [`Envelope`](crate::Envelope), the decoded object may not reference the
91/// original bytes. Otherwise, it would lead to a self-referential struct, which
92/// Rust doesn’t allow.
93///
94/// This constraint is maintained by requiring `T` to be
95/// [`DeserializeOwned`](serde::de::DeserializeOwned), which is automatically
96/// implemented by types that implement [`Deserialize`](serde::Deserialize) and
97/// don’t contain references.
98#[cfg(feature = "json")]
99pub struct JsonDecoder<T>(std::marker::PhantomData<T>);
100
101#[cfg(feature = "json")]
102impl<T> Default for JsonDecoder<T> {
103    fn default() -> Self {
104        Self(std::marker::PhantomData)
105    }
106}
107
108#[cfg(feature = "json")]
109impl<T> Decoder for JsonDecoder<T>
110where
111    T: serde::de::DeserializeOwned,
112{
113    type Result = T;
114    type Error = serde_json::Error;
115
116    fn decode(&self, bytes: &[u8]) -> Result<Self::Result, Self::Error> {
117        serde_json::from_slice(bytes)
118    }
119}