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> {
Box::new(self.clone())
}
fn as_any(&self) -> &dyn Any {
self
}
}