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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/// Code value in an ICMPv4 Redirect message.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum RedirectCode {
    /// Redirect Datagram for the Network (or subnet)
    RedirectForNetwork = 0,
    /// Redirect Datagram for the Host
    RedirectForHost = 1,
    /// Redirect Datagram for the Type of Service and Network
    RedirectForTypeOfServiceAndNetwork = 2,
    /// Redirect datagrams for the Type of Service and Host
    RedirectForTypeOfServiceAndHost = 3,
}

impl RedirectCode {
    /// Tries to convert a code [`u8`] value to a [`RedirectCode`] value.
    ///
    /// Returns [`None`] in case the code value is not known as a redirect code.
    #[inline]
    pub fn from_u8(code_u8: u8) -> Option<RedirectCode> {
        use crate::icmpv4::{RedirectCode::*, *};
        match code_u8 {
            CODE_REDIRECT_FOR_NETWORK => Some(RedirectForNetwork),
            CODE_REDIRECT_FOR_HOST => Some(RedirectForHost),
            CODE_REDIRECT_TYPE_OF_SERVICE_AND_NETWORK => Some(RedirectForTypeOfServiceAndNetwork),
            CODE_REDIRECT_TYPE_OF_SERVICE_AND_HOST => Some(RedirectForTypeOfServiceAndHost),
            _ => None,
        }
    }

    /// Returns the [`u8`] value of the code.
    #[inline]
    pub fn code_u8(&self) -> u8 {
        *self as u8
    }
}

#[cfg(test)]

mod test {
    use crate::icmpv4::{RedirectCode::*, *};
    use alloc::format;

    #[test]
    fn from_u8() {
        let tests = [
            (CODE_REDIRECT_FOR_NETWORK, RedirectForNetwork),
            (CODE_REDIRECT_FOR_HOST, RedirectForHost),
            (
                CODE_REDIRECT_TYPE_OF_SERVICE_AND_NETWORK,
                RedirectForTypeOfServiceAndNetwork,
            ),
            (
                CODE_REDIRECT_TYPE_OF_SERVICE_AND_HOST,
                RedirectForTypeOfServiceAndHost,
            ),
        ];
        for t in tests {
            assert_eq!(Some(t.1), RedirectCode::from_u8(t.0));
        }
        for code_u8 in 4..=u8::MAX {
            assert_eq!(None, RedirectCode::from_u8(code_u8));
        }
    }

    #[test]
    fn code_u8() {
        let tests = [
            (CODE_REDIRECT_FOR_NETWORK, RedirectForNetwork),
            (CODE_REDIRECT_FOR_HOST, RedirectForHost),
            (
                CODE_REDIRECT_TYPE_OF_SERVICE_AND_NETWORK,
                RedirectForTypeOfServiceAndNetwork,
            ),
            (
                CODE_REDIRECT_TYPE_OF_SERVICE_AND_HOST,
                RedirectForTypeOfServiceAndHost,
            ),
        ];
        for t in tests {
            assert_eq!(t.1.code_u8(), t.0);
        }
    }

    #[test]
    fn clone_eq() {
        let tests = [
            RedirectForNetwork,
            RedirectForHost,
            RedirectForTypeOfServiceAndNetwork,
            RedirectForTypeOfServiceAndHost,
        ];
        for t in tests {
            assert_eq!(t.clone(), t);
        }
    }

    #[test]
    fn debug() {
        let tests = [
            ("RedirectForNetwork", RedirectForNetwork),
            ("RedirectForHost", RedirectForHost),
            (
                "RedirectForTypeOfServiceAndNetwork",
                RedirectForTypeOfServiceAndNetwork,
            ),
            (
                "RedirectForTypeOfServiceAndHost",
                RedirectForTypeOfServiceAndHost,
            ),
        ];
        for t in tests {
            assert_eq!(t.0, format!("{:?}", t.1));
        }
    }
}