1 use super::{param_header::*, param_type::*, *};
2 
3 use bytes::{Buf, BufMut, Bytes, BytesMut};
4 use std::fmt;
5 
6 #[derive(Debug, Copy, Clone, PartialEq)]
7 #[repr(C)]
8 pub(crate) enum HmacAlgorithm {
9     HmacResv1 = 0,
10     HmacSha128 = 1,
11     HmacResv2 = 2,
12     HmacSha256 = 3,
13     Unknown,
14 }
15 
16 impl fmt::Display for HmacAlgorithm {
17     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18         let s = match *self {
19             HmacAlgorithm::HmacResv1 => "HMAC Reserved (0x00)",
20             HmacAlgorithm::HmacSha128 => "HMAC SHA-128",
21             HmacAlgorithm::HmacResv2 => "HMAC Reserved (0x02)",
22             HmacAlgorithm::HmacSha256 => "HMAC SHA-256",
23             _ => "Unknown HMAC Algorithm",
24         };
25         write!(f, "{s}")
26     }
27 }
28 
29 impl From<u16> for HmacAlgorithm {
30     fn from(v: u16) -> HmacAlgorithm {
31         match v {
32             0 => HmacAlgorithm::HmacResv1,
33             1 => HmacAlgorithm::HmacSha128,
34             2 => HmacAlgorithm::HmacResv2,
35             3 => HmacAlgorithm::HmacSha256,
36             _ => HmacAlgorithm::Unknown,
37         }
38     }
39 }
40 
41 #[derive(Default, Debug, Clone, PartialEq)]
42 pub(crate) struct ParamRequestedHmacAlgorithm {
43     pub(crate) available_algorithms: Vec<HmacAlgorithm>,
44 }
45 
46 impl fmt::Display for ParamRequestedHmacAlgorithm {
47     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48         write!(
49             f,
50             "{} {}",
51             self.header(),
52             self.available_algorithms
53                 .iter()
54                 .map(|ct| ct.to_string())
55                 .collect::<Vec<String>>()
56                 .join(" "),
57         )
58     }
59 }
60 
61 impl Param for ParamRequestedHmacAlgorithm {
62     fn header(&self) -> ParamHeader {
63         ParamHeader {
64             typ: ParamType::ReqHmacAlgo,
65             value_length: self.value_length() as u16,
66         }
67     }
68 
69     fn unmarshal(raw: &Bytes) -> Result<Self> {
70         let header = ParamHeader::unmarshal(raw)?;
71 
72         let reader =
73             &mut raw.slice(PARAM_HEADER_LENGTH..PARAM_HEADER_LENGTH + header.value_length());
74 
75         let mut available_algorithms = vec![];
76         let mut offset = 0;
77         while offset + 1 < header.value_length() {
78             let a: HmacAlgorithm = reader.get_u16().into();
79             if a == HmacAlgorithm::HmacSha128 || a == HmacAlgorithm::HmacSha256 {
80                 available_algorithms.push(a);
81             } else {
82                 return Err(Error::ErrInvalidAlgorithmType);
83             }
84 
85             offset += 2;
86         }
87 
88         Ok(ParamRequestedHmacAlgorithm {
89             available_algorithms,
90         })
91     }
92 
93     fn marshal_to(&self, buf: &mut BytesMut) -> Result<usize> {
94         self.header().marshal_to(buf)?;
95         for a in &self.available_algorithms {
96             buf.put_u16(*a as u16);
97         }
98         Ok(buf.len())
99     }
100 
101     fn value_length(&self) -> usize {
102         2 * self.available_algorithms.len()
103     }
104 
105     fn clone_to(&self) -> Box<dyn Param + Send + Sync> {
106         Box::new(self.clone())
107     }
108 
109     fn as_any(&self) -> &(dyn Any + Send + Sync) {
110         self
111     }
112 }
113