Skip to main content

wire_codec/
traits.rs

1//! Core traits implemented by every encodable value.
2//!
3//! [`Encode`] writes a value into a [`WriteBuf`]; [`Decode`] reads one out of a
4//! [`ReadBuf`]. The traits are deliberately minimal so callers can compose them
5//! with any framing strategy in the [`framing`][`crate::framing`] module.
6
7use crate::buf::{ReadBuf, WriteBuf};
8use crate::error::Result;
9
10/// A value that can be written to a [`WriteBuf`].
11///
12/// Implementors must guarantee that [`Encode::encoded_size`] returns the exact
13/// number of bytes [`Encode::encode`] writes on success.
14///
15/// # Example
16///
17/// ```
18/// use wire_codec::{Encode, Result, WriteBuf};
19///
20/// struct Tagged {
21///     tag: u8,
22///     value: u32,
23/// }
24///
25/// impl Encode for Tagged {
26///     fn encoded_size(&self) -> usize { 5 }
27///     fn encode(&self, buf: &mut WriteBuf<'_>) -> Result<()> {
28///         buf.write_u8(self.tag)?;
29///         buf.write_u32_be(self.value)
30///     }
31/// }
32///
33/// let mut out = [0u8; 5];
34/// let mut buf = WriteBuf::new(&mut out);
35/// Tagged { tag: 0x01, value: 0xCAFEBABE }.encode(&mut buf).unwrap();
36/// assert_eq!(&out, &[0x01, 0xCA, 0xFE, 0xBA, 0xBE]);
37/// ```
38pub trait Encode {
39    /// Number of bytes [`Encode::encode`] will write on success.
40    #[must_use]
41    fn encoded_size(&self) -> usize;
42
43    /// Write `self` into `buf`, advancing its write position.
44    ///
45    /// # Errors
46    ///
47    /// Returns an error if `buf` lacks capacity for [`Encode::encoded_size`]
48    /// bytes or if a sub-encoder reports an invariant violation.
49    fn encode(&self, buf: &mut WriteBuf<'_>) -> Result<()>;
50}
51
52/// A value that can be read from a [`ReadBuf`].
53///
54/// The lifetime parameter `'de` ties the decoded value to the borrowed input,
55/// enabling zero-copy decoding of borrowed payloads (`&'de [u8]`, `&'de str`).
56///
57/// # Example
58///
59/// ```
60/// use wire_codec::{Decode, ReadBuf, Result};
61///
62/// struct Tagged {
63///     tag: u8,
64///     value: u32,
65/// }
66///
67/// impl<'de> Decode<'de> for Tagged {
68///     fn decode(buf: &mut ReadBuf<'de>) -> Result<Self> {
69///         let tag = buf.read_u8()?;
70///         let value = buf.read_u32_be()?;
71///         Ok(Self { tag, value })
72///     }
73/// }
74///
75/// let mut buf = ReadBuf::new(&[0x01, 0xCA, 0xFE, 0xBA, 0xBE]);
76/// let tagged = Tagged::decode(&mut buf).unwrap();
77/// assert_eq!(tagged.tag, 0x01);
78/// assert_eq!(tagged.value, 0xCAFEBABE);
79/// ```
80pub trait Decode<'de>: Sized {
81    /// Read a value of `Self` from `buf`, advancing its read position.
82    ///
83    /// # Errors
84    ///
85    /// Returns an error if `buf` is exhausted before the value finishes, or if
86    /// the encoded bytes violate the codec's structural rules.
87    fn decode(buf: &mut ReadBuf<'de>) -> Result<Self>;
88}
89
90impl Encode for u8 {
91    #[inline]
92    fn encoded_size(&self) -> usize {
93        1
94    }
95    #[inline]
96    fn encode(&self, buf: &mut WriteBuf<'_>) -> Result<()> {
97        buf.write_u8(*self)
98    }
99}
100
101impl<'de> Decode<'de> for u8 {
102    #[inline]
103    fn decode(buf: &mut ReadBuf<'de>) -> Result<Self> {
104        buf.read_u8()
105    }
106}