encode/combinators/
length_prefix.rs

1use core::borrow::Borrow;
2use core::fmt::Debug;
3use core::marker::PhantomData;
4use core::ops::Deref;
5
6/// Encodes a length prefixed value ([TLV](https://en.wikipedia.org/wiki/Type–length–value)).
7///
8/// # Examples
9///
10/// ```rust
11/// # #[cfg(feature = "alloc")] {
12/// use encode::Encodable;
13/// use encode::combinators::LengthPrefix;
14/// use encode::combinators::FromError;
15/// use core::num::TryFromIntError;
16///
17/// let mut buf = Vec::new();
18/// LengthPrefix::<_, u8, TryFromIntError>::new("hello").encode(&mut buf).unwrap();
19/// assert_eq!(&buf, b"\x05hello", "Using a single byte to indicate the length of the string");
20/// # }
21/// ```
22#[doc(alias("length", "prefix", "TLV"))]
23#[repr(transparent)]
24pub struct LengthPrefix<Encodable, Length, Error> {
25    encodable: Encodable,
26    phantom: PhantomData<(Length, Error)>,
27}
28
29impl<Encodable, Length, Error> LengthPrefix<Encodable, Length, Error> {
30    /// Creates a new TLV combinator.
31    #[inline]
32    #[must_use]
33    pub const fn new(encodable: Encodable) -> Self {
34        Self {
35            encodable,
36            phantom: PhantomData,
37        }
38    }
39    /// Consumes the combinator and returns the inner encodable.
40    #[inline]
41    #[must_use]
42    pub fn into_inner(self) -> Encodable {
43        self.encodable
44    }
45}
46
47impl<Encodable, Length, Error> From<Encodable> for LengthPrefix<Encodable, Length, Error> {
48    #[inline]
49    fn from(value: Encodable) -> Self {
50        Self::new(value)
51    }
52}
53
54impl<Encodable, Length, Error> AsRef<Encodable> for LengthPrefix<Encodable, Length, Error> {
55    #[inline]
56    fn as_ref(&self) -> &Encodable {
57        &self.encodable
58    }
59}
60
61impl<Encodable, Length, Error> Deref for LengthPrefix<Encodable, Length, Error> {
62    type Target = Encodable;
63    #[inline]
64    fn deref(&self) -> &Self::Target {
65        self.as_ref()
66    }
67}
68
69impl<Encodable, Length, Error> Borrow<Encodable> for LengthPrefix<Encodable, Length, Error> {
70    #[inline]
71    fn borrow(&self) -> &Encodable {
72        &self.encodable
73    }
74}
75
76impl<Encodable, Length, Encoder, Error> crate::Encodable<Encoder>
77    for LengthPrefix<Encodable, Length, Error>
78where
79    Encoder: crate::BaseEncoder,
80    Encodable: crate::Encodable<Encoder> + crate::EncodableSize,
81    Length: crate::Encodable<Encoder> + TryFrom<usize>,
82    Error: From<<Length as crate::Encodable<Encoder>>::Error>
83        + From<<Length as TryFrom<usize>>::Error>
84        + From<<Encodable as crate::Encodable<Encoder>>::Error>
85        + From<<Encodable as crate::Encodable<crate::encoders::SizeEncoder>>::Error>
86        + From<Encoder::Error>,
87{
88    type Error = Error;
89
90    #[inline]
91    fn encode(&self, encoder: &mut Encoder) -> Result<(), Self::Error> {
92        let len = self.encodable.encoded_size()?;
93        let len_encoder = Length::try_from(len)?;
94
95        len_encoder.encode(encoder)?;
96        self.encodable.encode(encoder)?;
97        Ok(())
98    }
99}
100
101// Manual trait implementations because the derive macro does not support
102// phantom data fields.
103impl<Encodable, Length, Error> Debug for LengthPrefix<Encodable, Length, Error>
104where
105    Encodable: Debug,
106{
107    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
108        f.debug_struct("LengthPrefix")
109            .field("encodable", &self.encodable)
110            .finish()
111    }
112}
113impl<Encodable, Length, Error> Clone for LengthPrefix<Encodable, Length, Error>
114where
115    Encodable: Clone,
116{
117    #[inline]
118    fn clone(&self) -> Self {
119        Self {
120            encodable: self.encodable.clone(),
121            phantom: PhantomData,
122        }
123    }
124}
125impl<Encodable, Length, Error> Copy for LengthPrefix<Encodable, Length, Error> where Encodable: Copy {}
126impl<Encodable, Length, Error> Default for LengthPrefix<Encodable, Length, Error>
127where
128    Encodable: Default,
129{
130    #[inline]
131    fn default() -> Self {
132        Self {
133            encodable: Default::default(),
134            phantom: PhantomData,
135        }
136    }
137}
138impl<Encodable, Length, Error> PartialEq for LengthPrefix<Encodable, Length, Error>
139where
140    Encodable: PartialEq,
141{
142    #[inline]
143    fn eq(&self, other: &Self) -> bool {
144        self.encodable == other.encodable && self.phantom == other.phantom
145    }
146}
147impl<Encodable, Length, Error> Eq for LengthPrefix<Encodable, Length, Error> where Encodable: Eq {}
148impl<Encodable, Length, Error> PartialOrd for LengthPrefix<Encodable, Length, Error>
149where
150    Encodable: PartialOrd,
151{
152    #[inline]
153    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
154        self.encodable.partial_cmp(&other.encodable)
155    }
156}
157impl<Encodable, Length, Error> Ord for LengthPrefix<Encodable, Length, Error>
158where
159    Encodable: Ord,
160{
161    #[inline]
162    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
163        self.encodable.cmp(&other.encodable)
164    }
165}