use crate::{Buf, BufError, BufMut, BufResult, Codec, Cursor};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Option {
EndOfOptionList(EndOfOptionList),
NoOperation(NoOperation),
MaximumSegmentSize(MaximumSegmentSize),
WindowScale(WindowScale),
SackPermitted(SackPermitted),
Sack(Sack),
Timestamps(Timestamps),
Md5Signature(Md5Signature),
}
impl Codec for Option {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
match self {
Option::EndOfOptionList(opt) => opt.encode(writer, ()),
Option::NoOperation(opt) => opt.encode(writer, ()),
Option::MaximumSegmentSize(opt) => opt.encode(writer, ()),
Option::WindowScale(opt) => opt.encode(writer, ()),
Option::SackPermitted(opt) => opt.encode(writer, ()),
Option::Sack(opt) => opt.encode(writer, ()),
Option::Timestamps(opt) => opt.encode(writer, ()),
Option::Md5Signature(opt) => opt.encode(writer, ()),
}
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
let byte = reader.peek_u8()?;
let kind = Kind::try_from(byte).map_err(|_| BufError::UnexpectedValue)?;
match kind {
Kind::EndOfOptionList => Ok(Option::EndOfOptionList(EndOfOptionList::decode(
reader,
(),
)?)),
Kind::NoOperation => Ok(Option::NoOperation(NoOperation::decode(reader, ())?)),
Kind::MaximumSegmentSize => Ok(Option::MaximumSegmentSize(MaximumSegmentSize::decode(
reader,
(),
)?)),
Kind::WindowScale => Ok(Option::WindowScale(WindowScale::decode(reader, ())?)),
Kind::SackPermitted => Ok(Option::SackPermitted(SackPermitted::decode(reader, ())?)),
Kind::Sack => Ok(Option::Sack(Sack::decode(reader, ())?)),
Kind::Timestamps => Ok(Option::Timestamps(Timestamps::decode(reader, ())?)),
Kind::Md5Signature => Ok(Option::Md5Signature(Md5Signature::decode(reader, ())?)),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum Kind {
EndOfOptionList = 0,
NoOperation = 1,
MaximumSegmentSize = 2,
WindowScale = 3,
SackPermitted = 4,
Sack = 5,
Timestamps = 8,
Md5Signature = 19,
}
impl TryFrom<u8> for Kind {
type Error = ();
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Kind::EndOfOptionList),
1 => Ok(Kind::NoOperation),
2 => Ok(Kind::MaximumSegmentSize),
3 => Ok(Kind::WindowScale),
4 => Ok(Kind::SackPermitted),
5 => Ok(Kind::Sack),
8 => Ok(Kind::Timestamps),
19 => Ok(Kind::Md5Signature),
_ => Err(()),
}
}
}
impl Codec for Kind {
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> {
let byte = u8::decode(reader, ())?;
Self::try_from(byte).map_err(|_| BufError::UnexpectedValue)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct EndOfOptionList;
impl EndOfOptionList {
pub const KIND: Kind = Kind::EndOfOptionList;
}
impl Codec for EndOfOptionList {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::KIND.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
if Kind::decode(reader, ())? != Self::KIND {
return Err(BufError::UnexpectedValue);
}
Ok(Self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NoOperation;
impl NoOperation {
pub const KIND: Kind = Kind::NoOperation;
}
impl Codec for NoOperation {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::KIND.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
if Kind::decode(reader, ())? != Self::KIND {
return Err(BufError::UnexpectedValue);
}
Ok(Self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MaximumSegmentSize {
pub mss: u16,
}
impl MaximumSegmentSize {
pub const KIND: Kind = Kind::MaximumSegmentSize;
pub const LEN: u8 = 4;
}
impl Codec for MaximumSegmentSize {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::KIND.encode(writer, ())?;
Self::LEN.encode(writer, ())?;
self.mss.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
if Kind::decode(reader, ())? != Self::KIND {
return Err(BufError::UnexpectedValue);
}
if u8::decode(reader, ())? != Self::LEN {
return Err(BufError::UnexpectedValue);
}
Ok(Self {
mss: u16::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowScale {
pub shift_count: u8,
}
impl WindowScale {
pub const KIND: Kind = Kind::WindowScale;
pub const LEN: u8 = 3;
}
impl Codec for WindowScale {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::KIND.encode(writer, ())?;
Self::LEN.encode(writer, ())?;
self.shift_count.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
if Kind::decode(reader, ())? != Self::KIND {
return Err(BufError::UnexpectedValue);
}
if u8::decode(reader, ())? != Self::LEN {
return Err(BufError::UnexpectedValue);
}
Ok(Self {
shift_count: u8::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SackPermitted;
impl SackPermitted {
pub const KIND: Kind = Kind::SackPermitted;
pub const LEN: u8 = 2;
}
impl Codec for SackPermitted {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::KIND.encode(writer, ())?;
Self::LEN.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
if Kind::decode(reader, ())? != Self::KIND {
return Err(BufError::UnexpectedValue);
}
if u8::decode(reader, ())? != Self::LEN {
return Err(BufError::UnexpectedValue);
}
Ok(Self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SackBlock {
pub left_edge: u32,
pub right_edge: u32,
}
impl Codec for SackBlock {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.left_edge.encode(writer, ())?;
self.right_edge.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
Ok(Self {
left_edge: u32::decode(reader, ())?,
right_edge: u32::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Sack {
pub blocks: Vec<SackBlock>,
}
impl Sack {
pub const KIND: Kind = Kind::Sack;
pub const MIN_LEN: u8 = 2;
pub fn encoded_len(&self) -> u8 {
(2 + self.blocks.len() * 8) as u8
}
}
impl Codec for Sack {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::KIND.encode(writer, ())?;
self.encoded_len().encode(writer, ())?;
for block in &self.blocks {
block.encode(writer, ())?;
}
Ok(())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
if Kind::decode(reader, ())? != Self::KIND {
return Err(BufError::UnexpectedValue);
}
let length = u8::decode(reader, ())?;
if length < Self::MIN_LEN || (length - Self::MIN_LEN) % 8 != 0 {
return Err(BufError::InvalidLength);
}
let block_count = ((length - Self::MIN_LEN) / 8) as usize;
let mut blocks = Vec::with_capacity(block_count);
for _ in 0..block_count {
blocks.push(SackBlock::decode(reader, ())?);
}
Ok(Self { blocks })
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Timestamps {
pub tsval: u32,
pub tsecr: u32,
}
impl Timestamps {
pub const KIND: Kind = Kind::Timestamps;
pub const LEN: u8 = 10;
}
impl Codec for Timestamps {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::KIND.encode(writer, ())?;
Self::LEN.encode(writer, ())?;
self.tsval.encode(writer, ())?;
self.tsecr.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
if Kind::decode(reader, ())? != Self::KIND {
return Err(BufError::UnexpectedValue);
}
if u8::decode(reader, ())? != Self::LEN {
return Err(BufError::UnexpectedValue);
}
Ok(Self {
tsval: u32::decode(reader, ())?,
tsecr: u32::decode(reader, ())?,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Md5Signature {
pub digest: [u8; 16],
}
impl Md5Signature {
pub const KIND: Kind = Kind::Md5Signature;
pub const LEN: u8 = 18;
}
impl Codec for Md5Signature {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::KIND.encode(writer, ())?;
Self::LEN.encode(writer, ())?;
self.digest.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
if Kind::decode(reader, ())? != Self::KIND {
return Err(BufError::UnexpectedValue);
}
if u8::decode(reader, ())? != Self::LEN {
return Err(BufError::UnexpectedValue);
}
Ok(Self {
digest: reader.read_array::<16>()?,
})
}
}