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}