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
use super::{param_header::*, param_type::*, *};

use bytes::{Buf, BufMut, Bytes, BytesMut};
use std::fmt;

#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C)]
pub(crate) enum HmacAlgorithm {
    HmacResv1 = 0,
    HmacSha128 = 1,
    HmacResv2 = 2,
    HmacSha256 = 3,
    Unknown,
}

impl fmt::Display for HmacAlgorithm {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match *self {
            HmacAlgorithm::HmacResv1 => "HMAC Reserved (0x00)",
            HmacAlgorithm::HmacSha128 => "HMAC SHA-128",
            HmacAlgorithm::HmacResv2 => "HMAC Reserved (0x02)",
            HmacAlgorithm::HmacSha256 => "HMAC SHA-256",
            _ => "Unknown HMAC Algorithm",
        };
        write!(f, "{}", s)
    }
}

impl From<u16> for HmacAlgorithm {
    fn from(v: u16) -> HmacAlgorithm {
        match v {
            0 => HmacAlgorithm::HmacResv1,
            1 => HmacAlgorithm::HmacSha128,
            2 => HmacAlgorithm::HmacResv2,
            3 => HmacAlgorithm::HmacSha256,
            _ => HmacAlgorithm::Unknown,
        }
    }
}

#[derive(Default, Debug, Clone, PartialEq)]
pub(crate) struct ParamRequestedHmacAlgorithm {
    pub(crate) available_algorithms: Vec<HmacAlgorithm>,
}

impl fmt::Display for ParamRequestedHmacAlgorithm {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{} {}",
            self.header(),
            self.available_algorithms
                .iter()
                .map(|ct| ct.to_string())
                .collect::<Vec<String>>()
                .join(" "),
        )
    }
}

impl Param for ParamRequestedHmacAlgorithm {
    fn header(&self) -> ParamHeader {
        ParamHeader {
            typ: ParamType::ReqHmacAlgo,
            value_length: self.value_length() as u16,
        }
    }

    fn unmarshal(raw: &Bytes) -> Result<Self> {
        let header = ParamHeader::unmarshal(raw)?;

        let reader =
            &mut raw.slice(PARAM_HEADER_LENGTH..PARAM_HEADER_LENGTH + header.value_length());

        let mut available_algorithms = vec![];
        let mut offset = 0;
        while offset + 1 < header.value_length() {
            let a: HmacAlgorithm = reader.get_u16().into();
            if a == HmacAlgorithm::HmacSha128 || a == HmacAlgorithm::HmacSha256 {
                available_algorithms.push(a);
            } else {
                return Err(Error::ErrInvalidAlgorithmType);
            }

            offset += 2;
        }

        Ok(ParamRequestedHmacAlgorithm {
            available_algorithms,
        })
    }

    fn marshal_to(&self, buf: &mut BytesMut) -> Result<usize> {
        self.header().marshal_to(buf)?;
        for a in &self.available_algorithms {
            buf.put_u16(*a as u16);
        }
        Ok(buf.len())
    }

    fn value_length(&self) -> usize {
        2 * self.available_algorithms.len()
    }

    fn clone_to(&self) -> Box<dyn Param + Send + Sync> {
        Box::new(self.clone())
    }

    fn as_any(&self) -> &(dyn Any + Send + Sync) {
        self
    }
}