Skip to main content

reliar_core/
mapper.rs

1//! Transport mapping abstraction (ADR 0004). Implemented by transport crates such as
2//! `reliar-transport-nats`, never by `reliar-core` itself.
3
4use crate::SerializedEnvelope;
5
6/// Converts a [`SerializedEnvelope`] to and from one transport's native message type `M`.
7///
8/// No implementation ships from `reliar-core` — a mapper's transport headers are a
9/// **projection** of [`Metadata`](crate::Metadata), not a second source of truth (ADR 0004).
10/// The reserved `reliar-*` header names a mapper writes are a public contract that every
11/// transport crate follows so headers mean the same thing everywhere.
12///
13/// ```
14/// use reliar_core::{EnvelopeMapper, SerializedEnvelope};
15///
16/// /// A toy in-memory transport message: just the raw body, no headers.
17/// struct RawMessage(bytes::Bytes);
18///
19/// struct RawMapper;
20///
21/// #[derive(Debug)]
22/// struct RawMapError;
23/// impl core::fmt::Display for RawMapError {
24///     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
25///         f.write_str("cannot decode a bare payload back into an envelope")
26///     }
27/// }
28/// impl std::error::Error for RawMapError {}
29///
30/// impl EnvelopeMapper<RawMessage> for RawMapper {
31///     type Error = RawMapError;
32///
33///     fn encode(&self, envelope: &SerializedEnvelope) -> Result<RawMessage, Self::Error> {
34///         Ok(RawMessage(envelope.body.clone()))
35///     }
36///
37///     fn decode(&self, _message: RawMessage) -> Result<SerializedEnvelope, Self::Error> {
38///         // A real mapper reads the envelope's metadata back from transport headers; this toy
39///         // one has none to read, so decoding is always an error.
40///         Err(RawMapError)
41///     }
42/// }
43/// ```
44pub trait EnvelopeMapper<M> {
45    /// The mapper's own error type.
46    type Error: std::error::Error + Send + Sync + 'static;
47
48    /// Encodes a canonical envelope into the transport's native message type.
49    ///
50    /// # Errors
51    ///
52    /// Returns `Self::Error` if the transport's native message type cannot represent the
53    /// envelope (e.g. a field it cannot carry).
54    ///
55    /// ```
56    /// use reliar_core::{Envelope, EnvelopeMapper, Message};
57    /// # struct RawMessage(bytes::Bytes);
58    /// # struct RawMapper;
59    /// # #[derive(Debug)]
60    /// # struct RawMapError;
61    /// # impl core::fmt::Display for RawMapError {
62    /// #     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.write_str("nope") }
63    /// # }
64    /// # impl std::error::Error for RawMapError {}
65    /// # impl EnvelopeMapper<RawMessage> for RawMapper {
66    /// #     type Error = RawMapError;
67    /// #     fn encode(&self, envelope: &reliar_core::SerializedEnvelope) -> Result<RawMessage, Self::Error> {
68    /// #         Ok(RawMessage(envelope.body.clone()))
69    /// #     }
70    /// #     fn decode(&self, _message: RawMessage) -> Result<reliar_core::SerializedEnvelope, Self::Error> {
71    /// #         Err(RawMapError)
72    /// #     }
73    /// # }
74    ///
75    /// #[derive(serde::Serialize, serde::Deserialize)]
76    /// struct Ping;
77    /// impl Message for Ping {
78    ///     const TYPE: &'static str = "ping";
79    ///     const VERSION: u16 = 1;
80    /// }
81    ///
82    /// let envelope = Envelope::builder(Ping)
83    ///     .build()
84    ///     .map_body(|_| bytes::Bytes::from_static(b"{}"));
85    ///
86    /// let wire = RawMapper.encode(&envelope)?;
87    /// assert_eq!(wire.0.as_ref(), b"{}");
88    /// # Ok::<(), RawMapError>(())
89    /// ```
90    fn encode(&self, envelope: &SerializedEnvelope) -> Result<M, Self::Error>;
91
92    /// Decodes a transport message back into a canonical envelope.
93    ///
94    /// # Errors
95    ///
96    /// Returns `Self::Error` if the transport message cannot be decoded into a canonical
97    /// envelope (a missing required framework header, or a malformed one).
98    ///
99    /// ```
100    /// use reliar_core::EnvelopeMapper;
101    /// # struct RawMessage(bytes::Bytes);
102    /// # struct RawMapper;
103    /// # #[derive(Debug)]
104    /// # struct RawMapError;
105    /// # impl core::fmt::Display for RawMapError {
106    /// #     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.write_str("nope") }
107    /// # }
108    /// # impl std::error::Error for RawMapError {}
109    /// # impl EnvelopeMapper<RawMessage> for RawMapper {
110    /// #     type Error = RawMapError;
111    /// #     fn encode(&self, envelope: &reliar_core::SerializedEnvelope) -> Result<RawMessage, Self::Error> {
112    /// #         Ok(RawMessage(envelope.body.clone()))
113    /// #     }
114    /// #     fn decode(&self, _message: RawMessage) -> Result<reliar_core::SerializedEnvelope, Self::Error> {
115    /// #         Err(RawMapError)
116    /// #     }
117    /// # }
118    ///
119    /// // This toy mapper has no headers to read back, so decoding is always an error.
120    /// assert!(RawMapper.decode(RawMessage(bytes::Bytes::new())).is_err());
121    /// ```
122    fn decode(&self, message: M) -> Result<SerializedEnvelope, Self::Error>;
123}