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}