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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! An adaptor for non-fallible mappings over errors.

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

/// A decoder for applying a fallible transformation on the error type.
///
/// The result of [`crate::decode::DecoderExt::map_err`].
#[must_use = "decoders do nothing unless used"]
#[derive(Debug)]
pub struct DecoderMapErr<D, F> {
    inner: D,
    f: F,
}

impl<D, F> DecoderMapErr<D, F> {
    pub(in crate::decode) fn new(inner: D, f: F) -> Self {
        Self { inner, f }
    }
}

impl<D, F, A, E, EE> Decoder for DecoderMapErr<D, F>
where
    D: Decoder<Item = A, Error = E>,
    F: Fn(E) -> EE,
    E: From<io::Error>,
    EE: From<io::Error>,
{
    type Item = A;

    type Error = EE;

    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        self.inner.decode(src).map_err(&self.f)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    use crate::{decode::DecoderExt, primitives::uint8};

    #[test]
    fn decode_map_err_succeed() {
        let mut decoder = uint8()
            .try_map(|_| Ok::<_, io::Error>(0x42))
            .map_err(DecodeMapErrError::from);

        let mut src = BytesMut::from("\x01");
        let ok = decoder.decode(&mut src);

        assert_eq!(ok, Ok(Some(0x42)));
        assert_eq!(src, BytesMut::default());
    }

    #[test]
    fn decode_map_err_fail() {
        let mut decoder = uint8()
            .try_map(|_| Err::<u8, _>(io::Error::from(io::ErrorKind::Other)))
            .map_err(|e| DecodeMapErrError {
                kind: e.kind(),
                msg: "no particular reason".into(),
            });

        let mut src = BytesMut::from("\x01");
        let ok = decoder.decode(&mut src);

        assert_eq!(
            ok,
            Err(DecodeMapErrError {
                kind: io::ErrorKind::Other,
                msg: Some("no particular reason")
            })
        );
        assert_eq!(src, BytesMut::default());
    }

    #[derive(Debug, PartialEq, Eq)]
    struct DecodeMapErrError {
        kind: io::ErrorKind,
        msg: Option<&'static str>,
    }

    impl From<io::Error> for DecodeMapErrError {
        fn from(value: io::Error) -> Self {
            Self {
                kind: value.kind(),
                msg: None,
            }
        }
    }
}