ockam_core/
message.rs

1use crate::{
2    compat::{
3        string::{String, ToString},
4        vec::Vec,
5    },
6    errcode::{Kind, Origin},
7    Address, Error, LocalMessage, Result, Route,
8};
9use core::fmt::{self, Debug, Display, Formatter};
10use core::marker::PhantomData;
11use serde::{de::DeserializeOwned, Deserialize, Serialize};
12use serde_bare::ser::{Serializer, VecWrite};
13
14/// Alias of the type used for encoded data.
15pub type Encoded = Vec<u8>;
16
17/// A user-defined protocol identifier.
18///
19/// When creating workers that should asynchronously speak different
20/// protocols, this identifier can be used to switch message parsing
21/// between delegated workers, each responsible for only one protocol.
22///
23/// TODO @deprecated supplanted by the new metadata message types in
24///      `ockam::OckamMessage`
25#[derive(Serialize, Deserialize, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
26pub struct ProtocolId(String);
27
28impl ProtocolId {
29    /// Create a `None` protocol Id (with left pad).
30    pub fn none() -> Self {
31        Self(String::new())
32    }
33
34    /// Use the first 8 bytes of a string as the protocol ID.
35    #[allow(clippy::should_implement_trait)]
36    pub fn from_str(s: &str) -> Self {
37        Self(s.to_string())
38    }
39
40    /// Return the protocol as a `&str`.
41    pub fn as_str(&self) -> &str {
42        self.0.as_str()
43    }
44}
45
46impl From<&'static str> for ProtocolId {
47    fn from(s: &'static str) -> Self {
48        Self::from_str(s)
49    }
50}
51
52impl Display for ProtocolId {
53    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
54        write!(f, "{}", self.0)
55    }
56}
57
58/// Encode the type into an [`Encoded`] type.
59pub trait Encodable {
60    /// Encode the type into an [`Encoded`] type.
61    fn encode(self) -> Result<Encoded>;
62}
63
64/// Decode a slice.
65pub trait Decodable: Sized {
66    /// Decode a slice.
67    #[allow(clippy::ptr_arg)]
68    fn decode(e: &[u8]) -> Result<Self>;
69}
70
71/// A user defined message that can be serialised and deserialized.
72pub trait Message: Encodable + Decodable + Send + 'static {}
73
74impl Message for () {}
75
76impl Message for String {}
77
78impl Message for Vec<u8> {}
79
80impl Encodable for Vec<u8> {
81    fn encode(self) -> Result<Encoded> {
82        Ok(self)
83    }
84}
85
86impl Decodable for Vec<u8> {
87    fn decode(e: &[u8]) -> Result<Self> {
88        Ok(e.to_vec())
89    }
90}
91
92impl Encodable for () {
93    fn encode(self) -> Result<Encoded> {
94        Ok(vec![])
95    }
96}
97
98impl Decodable for () {
99    fn decode(_e: &[u8]) -> Result<Self> {
100        Ok(())
101    }
102}
103
104impl Encodable for String {
105    fn encode(self) -> Result<Encoded> {
106        serialize(self)
107    }
108}
109
110impl Decodable for String {
111    fn decode(e: &[u8]) -> Result<Self> {
112        deserialize(e)
113    }
114}
115
116/// Serialize a type using serde_bare
117pub fn serialize<T: Serialize>(t: T) -> Result<Encoded> {
118    let mut vec = Vec::new();
119    let mut serializer = Serializer::new(VecWrite::new(&mut vec));
120    t.serialize(&mut serializer)?;
121    Ok(vec)
122}
123
124/// Serialize a type using serde_bare
125pub fn deserialize<T: DeserializeOwned>(encoded: &[u8]) -> Result<T> {
126    Ok(serde_bare::from_slice(encoded)?)
127}
128
129/// A message type that is not subject to any encoding or decoding.
130#[derive(Debug, Clone)]
131pub struct NeutralMessage(Vec<u8>);
132
133impl NeutralMessage {
134    /// Returns the inner Vec<u8> of the NeutralMessage
135    pub fn into_vec(self) -> Vec<u8> {
136        self.0
137    }
138}
139
140impl From<Vec<u8>> for NeutralMessage {
141    fn from(v: Vec<u8>) -> Self {
142        Self(v)
143    }
144}
145
146impl From<NeutralMessage> for Vec<u8> {
147    fn from(m: NeutralMessage) -> Self {
148        m.0
149    }
150}
151
152impl Encodable for NeutralMessage {
153    fn encode(self) -> Result<Encoded> {
154        Ok(self.0)
155    }
156}
157
158impl Decodable for NeutralMessage {
159    fn decode(v: &[u8]) -> Result<Self> {
160        Ok(Self(v.to_vec()))
161    }
162}
163
164impl Message for NeutralMessage {}
165
166impl From<serde_bare::error::Error> for Error {
167    #[track_caller]
168    fn from(e: serde_bare::error::Error) -> Self {
169        Error::new(Origin::Core, Kind::Io, e)
170    }
171}
172
173impl From<minicbor::decode::Error> for Error {
174    #[track_caller]
175    fn from(e: minicbor::decode::Error) -> Self {
176        Error::new(Origin::Unknown, Kind::Invalid, e)
177    }
178}
179
180#[cfg(feature = "std")]
181impl<E> From<minicbor::encode::Error<E>> for Error
182where
183    E: std::error::Error + Send + Sync + 'static,
184{
185    #[track_caller]
186    fn from(e: minicbor::encode::Error<E>) -> Self {
187        Error::new(Origin::Unknown, Kind::Invalid, e)
188    }
189}
190
191#[cfg(not(feature = "std"))]
192impl<E: Display> From<minicbor::encode::Error<E>> for Error {
193    #[track_caller]
194    fn from(e: minicbor::encode::Error<E>) -> Self {
195        Error::new(Origin::Unknown, Kind::Invalid, e)
196    }
197}
198
199/// A message wrapper that provides message route information.
200///
201/// Workers can accept arbitrary message types, which may not contain
202/// information about their routes.
203///
204/// However, the Ockam worker and messaging system already keeps track
205/// of this information internally.
206///
207/// This type makes it possible to expose this information to the
208/// user, without requiring changes to the user's message types.
209///
210/// # Examples
211///
212/// See `ockam_node::WorkerRelay` for a usage example.
213///
214pub struct Routed<M: Message> {
215    /// Phantom field to keep track of the message type.
216    phantom: PhantomData<M>,
217    /// The address of the wrapped message.
218    msg_addr: Address,
219    /// True sender of the message (guaranteed by the implementation)
220    /// May be different from a return_route first hop
221    src_addr: Address,
222    /// A `LocalMessage` that contains routing information for the wrapped message.
223    local_msg: LocalMessage,
224}
225
226impl<M: Message> Routed<M> {
227    /// Create a new `Routed` message wrapper from the given message,
228    /// message address and a local message that contains routing
229    /// information.
230    pub fn new(msg_addr: Address, src_addr: Address, local_msg: LocalMessage) -> Self {
231        Self {
232            phantom: PhantomData,
233            msg_addr,
234            src_addr,
235            local_msg,
236        }
237    }
238
239    /// Return a copy of the message address.
240    #[inline]
241    pub fn msg_addr(&self) -> &Address {
242        &self.msg_addr
243    }
244
245    /// True sender of the message
246    #[inline]
247    pub fn src_addr(&self) -> &Address {
248        &self.src_addr
249    }
250
251    /// Return a copy of the onward route for the wrapped message.
252    #[inline]
253    pub fn onward_route(&self) -> &Route {
254        self.local_msg.onward_route()
255    }
256
257    /// Return a copy of the full return route for the wrapped message.
258    #[inline]
259    pub fn return_route(&self) -> &Route {
260        self.local_msg.return_route()
261    }
262    /// Return a copy of the sender address for the wrapped message.
263    #[inline]
264    pub fn sender(&self) -> Result<&Address> {
265        self.local_msg.return_route().recipient()
266    }
267
268    /// Consume the message wrapper and return the original message.
269    #[inline]
270    pub fn into_body(self) -> Result<M> {
271        M::decode(&self.into_payload())
272    }
273
274    /// Consume the message wrapper and return the underlying local message.
275    #[inline]
276    pub fn into_local_message(self) -> LocalMessage {
277        self.local_msg
278    }
279
280    /// Return a reference to the underlying local message.
281    #[inline]
282    pub fn local_message(&self) -> &LocalMessage {
283        &self.local_msg
284    }
285
286    /// Return a reference to the underlying transport message's binary payload.
287    #[inline]
288    pub fn payload(&self) -> &[u8] {
289        self.local_msg.payload()
290    }
291
292    /// Consume the message wrapper and return the underlying transport message's binary payload.
293    #[inline]
294    pub fn into_payload(self) -> Vec<u8> {
295        self.local_msg.into_payload()
296    }
297}
298
299impl<M: Message + Debug> Debug for Routed<M> {
300    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
301        f.debug_struct("Routed")
302            .field("msg_addr", &self.msg_addr)
303            .field("src_addr", &self.src_addr)
304            .field("type", &core::any::type_name::<M>())
305            .field("local_msg", &self.local_msg)
306            .finish()
307    }
308}
309
310/// A passthrough marker message type.
311///
312/// This is a special message type which will enable your worker to
313/// accept _any_ typed message, by ignoring the type information in
314/// the payload.
315///
316/// This is especially useful for implementing middleware workers
317/// which need access to the route information of a message, without
318/// understanding its payload.
319///
320/// # Examples
321///
322/// ```ignore
323/// use ockam::{hex, Any, Context, Result, Routed, Worker};
324///
325/// pub struct Logger;
326///
327/// #[ockam::worker]
328/// impl Worker for Logger {
329///     type Context = Context;
330///     type Message = Any;
331///
332///     /// This Worker will take any incoming message, print out the payload
333///     /// and then forward it to the next hop in its onward route.
334///     async fn handle_message(&mut self, ctx: &mut Context, msg: Routed<Any>) -> Result<()> {
335///         let mut local_msg = msg.into_local_message();///
336///         let payload = local_msg.payload_ref();
337///
338///         if let Ok(str) = String::from_utf8(payload.to_vec()) {
339///             println!("Address: {}, Received string: {}", ctx.address(), str);
340///         } else {
341///             println!("Address: {}, Received binary: {}", ctx.address(), hex::encode(&payload));
342///         }
343///
344///         ctx.forward(local_msg).await
345///     }
346/// }
347/// ```
348#[derive(Clone, Debug, PartialEq, Eq, crate::Message)]
349pub struct Any;
350
351impl Display for Any {
352    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
353        write!(f, "Any Message")
354    }
355}
356
357impl Encodable for Any {
358    fn encode(self) -> Result<Encoded> {
359        Ok(vec![])
360    }
361}
362
363impl Decodable for Any {
364    fn decode(_: &[u8]) -> Result<Self> {
365        Ok(Self)
366    }
367}