tokio_util_codec_compose/primitives/
ints.rs

1//! Codec for integers.
2
3use bytes::{Buf, BufMut};
4
5/// Codec for an [`u8`].
6///
7/// # Examples
8///
9/// ## Decoding
10///
11/// ```
12/// # use bytes::BytesMut;
13/// # use tokio_util::codec::Decoder;
14/// # use tokio_util_codec_compose::primitives::ints::U8;
15/// let mut decoder = U8::default();
16///
17/// let res = decoder.decode(&mut BytesMut::from("\x2A")).unwrap();
18///
19/// assert_eq!(res, Some(42))
20/// ```
21///
22/// ## Encoding
23///
24/// ```
25/// # use bytes::BytesMut;
26/// # use tokio_util::codec::Encoder;
27/// # use tokio_util_codec_compose::primitives::ints::U8;
28/// let mut encoder = U8::default();
29///
30/// let mut dst = BytesMut::default();
31/// encoder.encode(0x2A, &mut dst).unwrap();
32///
33/// assert_eq!(dst, BytesMut::from("\x2A"))
34/// ```
35#[must_use = "decoders do nothing unless used"]
36#[derive(Debug, Default)]
37pub struct U8;
38
39/// Codec for an [`u16`] big-endian.
40///
41/// # Examples
42///
43/// ## Decoding
44///
45/// ```
46/// # use bytes::BytesMut;
47/// # use tokio_util::codec::Decoder;
48/// # use tokio_util_codec_compose::primitives::ints::U16BE;
49/// let mut decoder = U16BE::default();
50///
51/// let res = decoder.decode(&mut BytesMut::from("\x2A\x3B")).unwrap();
52///
53/// assert_eq!(res, Some(0x2A3B))
54/// ```
55///
56/// ## Encoding
57///
58/// ```
59/// # use bytes::BytesMut;
60/// # use tokio_util::codec::Encoder;
61/// # use tokio_util_codec_compose::primitives::ints::U16BE;
62/// let mut encoder = U16BE::default();
63///
64/// let mut dst = BytesMut::default();
65/// encoder.encode(0x2A3B, &mut dst).unwrap();
66///
67/// assert_eq!(dst, BytesMut::from("\x2A\x3B"))
68/// ```
69#[must_use = "codecs do nothing unless used"]
70#[derive(Debug, Default)]
71pub struct U16BE;
72
73/// Codec for an [`u16`] little-endian.
74///
75/// # Examples
76///
77/// ## Decoding
78///
79/// ```
80/// # use bytes::BytesMut;
81/// # use tokio_util::codec::Decoder;
82/// # use tokio_util_codec_compose::primitives::ints::U16LE;
83/// let mut decoder = U16LE::default();
84///
85/// let res = decoder.decode(&mut BytesMut::from("\x2A\x3B")).unwrap();
86///
87/// assert_eq!(res, Some(0x3B2A))
88/// ```
89///
90/// ## Encoding
91///
92/// ```
93/// # use bytes::BytesMut;
94/// # use tokio_util::codec::Encoder;
95/// # use tokio_util_codec_compose::primitives::ints::U16LE;
96/// let mut encoder = U16LE::default();
97///
98/// let mut dst = BytesMut::default();
99/// encoder.encode(0x2A3B, &mut dst).unwrap();
100///
101/// assert_eq!(dst, BytesMut::from("\x3B\x2A"))
102/// ```
103#[must_use = "codecs do nothing unless used"]
104#[derive(Debug, Default)]
105pub struct U16LE;
106
107/// Codec for an [`u32`] big-endian.
108///
109/// # Examples
110///
111/// ## Decoding
112///
113/// ```
114/// # use bytes::BytesMut;
115/// # use tokio_util::codec::Decoder;
116/// # use tokio_util_codec_compose::primitives::ints::U32BE;
117/// let mut decoder = U32BE::default();
118///
119/// let res = decoder.decode(&mut BytesMut::from("\x2A\x3B\x4C\x5D")).unwrap();
120///
121/// assert_eq!(res, Some(0x2A3B4C5D))
122/// ```
123///
124/// ## Encoding
125///
126/// ```
127/// # use bytes::BytesMut;
128/// # use tokio_util::codec::Encoder;
129/// # use tokio_util_codec_compose::primitives::ints::U32BE;
130/// let mut encoder = U32BE::default();
131///
132/// let mut dst = BytesMut::default();
133/// encoder.encode(0x2A3B4C5D, &mut dst).unwrap();
134///
135/// assert_eq!(dst, BytesMut::from("\x2A\x3B\x4C\x5D"))
136/// ```
137#[must_use = "codecs do nothing unless used"]
138#[derive(Debug, Default)]
139pub struct U32BE;
140
141/// Codec for an [`u32`] little-endian.
142///
143/// # Examples
144///
145/// ## Decoding
146///
147/// ```
148/// # use bytes::BytesMut;
149/// # use tokio_util::codec::Decoder;
150/// # use tokio_util_codec_compose::primitives::ints::U32LE;
151/// let mut decoder = U32LE::default();
152///
153/// let res = decoder.decode(&mut BytesMut::from("\x2A\x3B\x4C\x5D")).unwrap();
154///
155/// assert_eq!(res, Some(0x5D4C3B2A))
156/// ```
157///
158/// ## Encoding
159///
160/// ```
161/// # use bytes::BytesMut;
162/// # use tokio_util::codec::Encoder;
163/// # use tokio_util_codec_compose::primitives::ints::U32LE;
164/// let mut encoder = U32LE::default();
165///
166/// let mut dst = BytesMut::default();
167/// encoder.encode(0x5D4C3B2A, &mut dst).unwrap();
168///
169/// assert_eq!(dst, BytesMut::from("\x2A\x3B\x4C\x5D"))
170/// ```
171#[must_use = "codecs do nothing unless used"]
172#[derive(Debug, Default)]
173pub struct U32LE;
174
175macro_rules! impl_decoder {
176    ($type:ty, $value:ty, $len:expr, $get:ident) => {
177        impl ::tokio_util::codec::Decoder for $type {
178            type Item = $value;
179
180            type Error = std::io::Error;
181
182            fn decode(
183                &mut self,
184                src: &mut ::bytes::BytesMut,
185            ) -> Result<Option<Self::Item>, Self::Error> {
186                if src.len() < $len {
187                    Ok(None)
188                } else {
189                    Ok(src.$get().into())
190                }
191            }
192        }
193    };
194}
195
196impl_decoder!(U8, u8, 1, get_u8);
197impl_decoder!(U16BE, u16, 2, get_u16);
198impl_decoder!(U16LE, u16, 2, get_u16_le);
199impl_decoder!(U32BE, u32, 4, get_u32);
200impl_decoder!(U32LE, u32, 4, get_u32_le);
201
202macro_rules! impl_encoder {
203    ($type:ty, $value:ty, $len:expr, $put:ident) => {
204        impl ::tokio_util::codec::Encoder<$value> for $type {
205            type Error = std::io::Error;
206
207            fn encode(
208                &mut self,
209                item: $value,
210                dst: &mut ::bytes::BytesMut,
211            ) -> Result<(), Self::Error> {
212                dst.reserve($len);
213                dst.$put(item);
214                Ok(())
215            }
216        }
217    };
218}
219
220impl_encoder!(U8, u8, 1, put_u8);
221impl_encoder!(U16BE, u16, 2, put_u16);
222impl_encoder!(U16LE, u16, 2, put_u16_le);
223impl_encoder!(U32BE, u32, 4, put_u32);
224impl_encoder!(U32LE, u32, 4, put_u32_le);
225
226#[cfg(test)]
227mod tests {
228    use super::*;
229    use anyhow::Result;
230    use bytes::BytesMut;
231    use std::{error, fmt::Debug};
232    use tokio_util::codec::Decoder;
233
234    #[test]
235    fn u8_decode() -> Result<()> {
236        check(CheckOpts {
237            decoder: U8,
238            src: BytesMut::from("\x2A\x00\x01\x02\x03"),
239            expected_output: 0x2A,
240            expected_remainder: BytesMut::from("\x00\x01\x02\x03"),
241        })
242    }
243
244    #[test]
245    fn u16be_decode() -> Result<()> {
246        check(CheckOpts {
247            decoder: U16BE,
248            src: BytesMut::from("\x2A\x3B\x01\x02\x03"),
249            expected_output: 0x2A3B,
250            expected_remainder: BytesMut::from("\x01\x02\x03"),
251        })
252    }
253
254    #[test]
255    fn u16le_decode() -> Result<()> {
256        check(CheckOpts {
257            decoder: U16LE,
258            src: BytesMut::from("\x2A\x3B\x01\x02\x03"),
259            expected_output: 0x3B2A,
260            expected_remainder: BytesMut::from("\x01\x02\x03"),
261        })
262    }
263
264    #[test]
265    fn u32be_decode() -> Result<()> {
266        check(CheckOpts {
267            decoder: U32BE,
268            src: BytesMut::from("\x2A\x3B\x01\x02\x03"),
269            expected_output: 0x2A3B_0102,
270            expected_remainder: BytesMut::from("\x03"),
271        })
272    }
273
274    #[test]
275    fn u32le_decode() -> Result<()> {
276        check(CheckOpts {
277            decoder: U32LE,
278            src: BytesMut::from("\x2A\x3B\x01\x02\x03"),
279            expected_output: 0x0201_3B2A,
280            expected_remainder: BytesMut::from("\x03"),
281        })
282    }
283
284    #[track_caller]
285    fn check<D, A>(
286        CheckOpts {
287            mut decoder,
288            mut src,
289            expected_output,
290            expected_remainder,
291        }: CheckOpts<D, A>,
292    ) -> Result<()>
293    where
294        D: Decoder<Item = A>,
295        A: PartialEq + Debug,
296        D::Error: error::Error + Send + Sync + 'static,
297    {
298        let output = decoder.decode(&mut src)?;
299
300        assert_eq!(output, Some(expected_output));
301        assert_eq!(src, expected_remainder);
302
303        Ok(())
304    }
305
306    #[derive(Debug)]
307    struct CheckOpts<D, A> {
308        decoder: D,
309        src: BytesMut,
310        expected_output: A,
311        expected_remainder: BytesMut,
312    }
313}