use crate::{
Buf,
BufError::{self},
BufMut, BufResult, Codec, Cursor,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum ChangeCipherSpecType {
ChangeCipherSpec = 1,
}
impl Codec for ChangeCipherSpecType {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
(*self as u8).encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
match u8::decode(reader, ())? {
x if x == (Self::ChangeCipherSpec as u8) => Ok(Self::ChangeCipherSpec),
_ => Err(BufError::UnexpectedValue),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChangeCipherSpec {
pub type_: ChangeCipherSpecType,
}
impl Codec for ChangeCipherSpec {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.type_.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
type_: ChangeCipherSpecType::decode(reader, ())?,
})
}
}
#[cfg(test)]
mod tests {
use core::fmt::Debug;
use super::{ChangeCipherSpec, ChangeCipherSpecType};
use crate::{Codec, Cursor};
fn codec_roundtrip<T: Codec<C> + Debug + Eq, C: Copy>(
etalon_struct: T,
etalon_bytes: &[u8],
context: C,
) {
let mut encoded_bytes = vec![];
{
let writer = &mut Cursor::new(&mut encoded_bytes);
etalon_struct.encode(writer, context).unwrap();
}
assert_eq!(etalon_bytes, &encoded_bytes);
let decoded_struct = {
let reader = &mut Cursor::new(&mut encoded_bytes);
T::decode(reader, context).unwrap()
};
assert_eq!(etalon_struct, decoded_struct);
encoded_bytes.fill(0x00);
{
let writer = &mut Cursor::new(&mut encoded_bytes);
decoded_struct.encode(writer, context).unwrap();
}
assert_eq!(etalon_bytes, &encoded_bytes);
}
#[test]
fn change_cipher_spec() {
let etalon_bytes = &[0x01];
let etalon_struct = ChangeCipherSpec {
type_: ChangeCipherSpecType::ChangeCipherSpec,
};
codec_roundtrip(etalon_struct, etalon_bytes, ());
}
}