tokio_util_codec_compose/encode/adaptors/
contra_map.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//! An adaptor for non-fallible mappings.

use bytes::BytesMut;
use std::io;
use tokio_util::codec::Encoder;

/// An encoder for applying a non-fallible transformation.
///
/// The result of [`crate::encode::EncoderExt::contra_map`].
#[must_use = "encoders do nothing unless used"]
#[derive(Debug)]
pub struct EncoderContraMap<C, F> {
    inner: C,
    f: F,
}

impl<C, F> EncoderContraMap<C, F> {
    pub(in crate::encode) fn new(inner: C, f: F) -> Self {
        Self { inner, f }
    }
}

impl<C, F, A, B, E> Encoder<B> for EncoderContraMap<C, F>
where
    C: Encoder<A, Error = E>,
    F: Fn(B) -> A,
    E: From<io::Error>,
{
    type Error = E;

    fn encode(&mut self, item: B, dst: &mut BytesMut) -> Result<(), Self::Error> {
        self.inner.encode((self.f)(item), dst)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::encode::EncoderExt;
    use bytes::BufMut;

    #[test]
    fn encode_contra_map() -> anyhow::Result<()> {
        let mut encoder = U8::default().contra_map(|d: Device| d.0);

        let mut dst = BytesMut::default();
        encoder.encode(Device(0x01), &mut dst)?;

        assert_eq!(dst, BytesMut::from("\x01"));

        Ok(())
    }

    #[derive(Debug, PartialEq, Eq)]
    struct Device(u8);

    #[derive(Debug, Default, PartialEq, Eq)]
    struct U8(u8);

    impl Encoder<u8> for U8 {
        type Error = io::Error;

        fn encode(&mut self, item: u8, dst: &mut BytesMut) -> Result<(), Self::Error> {
            dst.reserve(1);
            dst.put_u8(item);
            Ok(())
        }
    }
}