rm_frame/marshaler.rs
1//! Defines the [`Marshaler`] trait and related traits for payload serialization and deserialization.
2
3use crate::MarshalerError;
4
5type Result<T> = core::result::Result<T, MarshalerError>;
6
7///
8/// Payload marshaling interface.
9///
10/// [`Marshaler`] defines how a message payload is:
11/// - Serialized into raw bytes ([`Marshaler::marshal`])
12/// - Deserialized from raw bytes ([`Marshaler::unmarshal`])
13///
14/// Each payload type corresponds to exactly one command ID.
15///
16pub trait Marshaler: Sized {
17 /// Command ID associated with this payload type.
18 const CMD_ID: u16;
19 /// Expected size of the payload in bytes.
20 const PAYLOAD_SIZE: u16;
21
22 ///
23 /// Serialize the payload into the destination buffer.
24 ///
25 /// Returns the number of bytes written on success.
26 ///
27 /// # Notes
28 ///
29 /// If called manually, the caller must ensure
30 /// that the destination buffer is large enough
31 /// to hold the serialized payload.
32 ///
33 /// # Errors
34 ///
35 /// Returns an error if the destination buffer
36 /// is too small or the payload cannot be encoded.
37 ///
38 fn marshal(&self, dst: &mut [u8]) -> Result<usize>;
39
40 ///
41 /// Deserialize a payload from raw bytes.
42 ///
43 /// The input slice contains only the payload portion
44 /// (no header, command ID, or CRC).
45 ///
46 /// Implementations must not depend on framing details.
47 ///
48 /// # Errors
49 ///
50 /// Returns an error if the data is invalid
51 /// or does not match the expected payload format.
52 ///
53 fn unmarshal(raw: &[u8]) -> Result<Self>;
54}
55
56/// Provides the command ID and payload size constants for a message type.
57///
58/// This trait is a sub-trait of [`Marshaler`] and is automatically implemented
59/// for any type that implements [`Marshaler`]. It can also be implemented
60/// directly when only the metadata constants are needed.
61pub trait ImplCommandMsg: Sized {
62 /// See [`Marshaler::CMD_ID`] for details.
63 const CMD_ID: u16;
64 /// See [`Marshaler::PAYLOAD_SIZE`] for details.
65 const PAYLOAD_SIZE: u16;
66}
67
68impl<T: Marshaler> ImplCommandMsg for T {
69 const CMD_ID: u16 = T::CMD_ID;
70 const PAYLOAD_SIZE: u16 = T::PAYLOAD_SIZE;
71}
72
73/// Payload serialization half of [`Marshaler`].
74///
75/// Automatically implemented for any type that implements [`Marshaler`].
76/// Implement this trait directly — without implementing [`Marshaler`] —
77/// to create an encode-only type that does not support deserialization.
78///
79/// Used as the bound on [`Messager::pack`](crate::Messager::pack).
80pub trait ImplMarshal: ImplCommandMsg {
81 /// See [`Marshaler::marshal`] for details.
82 fn marshal(&self, dst: &mut [u8]) -> Result<usize>;
83}
84
85impl<T: Marshaler> ImplMarshal for T {
86 fn marshal(&self, dst: &mut [u8]) -> Result<usize> {
87 T::marshal(self, dst)
88 }
89}
90
91/// Payload deserialization half of [`Marshaler`].
92///
93/// Automatically implemented for any type that implements [`Marshaler`].
94/// Implement this trait directly — without implementing [`Marshaler`] —
95/// to create a decode-only type that does not support serialization.
96///
97/// Used as the bound on [`Messager::unmarshal`](crate::Messager::unmarshal) and [`RawFrame::unmarshal`](crate::RawFrame::unmarshal).
98pub trait ImplUnMarshal: ImplCommandMsg {
99 /// See [`Marshaler::unmarshal`] for details.
100 fn unmarshal(raw: &[u8]) -> Result<Self>;
101}
102
103impl<T: Marshaler> ImplUnMarshal for T {
104 fn unmarshal(raw: &[u8]) -> Result<Self> {
105 T::unmarshal(raw)
106 }
107}