tokio_util_codec_compose/decode/adaptors/
map.rs

1//! An adaptor for non-fallible mappings.
2
3use bytes::BytesMut;
4use std::io;
5use tokio_util::codec::Decoder;
6
7/// A decoder for applying a non-fallible transformation on the success type.
8///
9/// The result of [`crate::decode::DecoderExt::map`].
10#[must_use = "decoders do nothing unless used"]
11#[derive(Debug)]
12pub struct DecoderMap<D, F> {
13    inner: D,
14    f: F,
15}
16
17impl<D, F> DecoderMap<D, F> {
18    pub(in crate::decode) fn new(inner: D, f: F) -> Self {
19        Self { inner, f }
20    }
21}
22
23impl<D, F, A, B, E> Decoder for DecoderMap<D, F>
24where
25    D: Decoder<Item = A, Error = E>,
26    F: Fn(A) -> B,
27    E: From<io::Error>,
28{
29    type Item = B;
30
31    type Error = E;
32
33    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
34        Ok(self.inner.decode(src)?.map(&self.f))
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    use crate::{decode::DecoderExt, primitives::uint8};
43
44    use proptest::prelude::*;
45    use std::{convert::identity as id, fmt::Debug};
46    use tokio_util::codec::BytesCodec;
47
48    // TODO: Check laws.
49
50    proptest! {
51        #[test]
52        fn decode_map_check_law_map_id(src in bytes()) {
53            // TODO: Generate multiple decoders synced with valid byte-sequences with success/failure.
54            let src = BytesMut::from(src.as_slice());
55            let decoder = BytesCodec::default();
56            decode_map_law_map_id_succeed(decoder, src);
57        }
58    }
59
60    #[track_caller]
61    fn decode_map_law_map_id_succeed<D, A, E>(mut decoder: D, mut src: BytesMut)
62    where
63        D: Decoder<Item = A, Error = E> + Clone,
64        A: PartialEq + Debug,
65        E: Debug + From<io::Error>,
66    {
67        let mut src_mapped = src.clone();
68        let mut decoder_mapped = decoder.clone().map(id);
69
70        let res = decoder.decode(&mut src).unwrap();
71        let res_mapped = decoder_mapped.decode(&mut src_mapped).unwrap();
72
73        assert_eq!(res, res_mapped);
74        assert_eq!(src, src_mapped);
75    }
76
77    fn bytes() -> impl Strategy<Value = Vec<u8>> {
78        proptest::collection::vec(any::<u8>(), 0..255)
79    }
80
81    #[test]
82    fn decode_map() -> anyhow::Result<()> {
83        let mut decoder = uint8().map(Device);
84
85        let mut src = BytesMut::from("\x01");
86        let value = decoder.decode(&mut src)?;
87
88        assert!(matches!(value, Some(Device(0x01))));
89        assert_eq!(src, BytesMut::default());
90
91        Ok(())
92    }
93
94    #[derive(Debug, PartialEq, Eq)]
95    struct Device(u8);
96}