pn-dcp 0.3.0

Aim to quickly parsing and splicing pn-dcp packet
Documentation
use crate::block::{BlockPadding, BlockSet, BlockTrait};
use crate::comm::BytesWrap;
use crate::options::{BlockQualifier, OptionAndSubValue};
use crate::packet::{DcpHead, PnDcp, PnDcpTy};
use anyhow::bail;
use pn_dcp_macro::derefmut;
use pnet::datalink::MacAddr;
use std::ops::{Deref, DerefMut};

#[derive(Debug, Eq, PartialEq, Clone)]
#[derefmut(head)]
pub struct PacketSetReq {
    head: DcpHead,
    blocks: BlockSet,
}
impl Deref for PacketSetReq {
    type Target = DcpHead;

    fn deref(&self) -> &Self::Target {
        &self.head
    }
}
impl PacketSetReq {
    pub fn new(
        source: MacAddr,
        dest: MacAddr,
        option: OptionAndSubValue,
        qualifier: BlockQualifier,
    ) -> Self {
        let mut head = DcpHead::new(dest, source, PnDcpTy::SetReq);
        let blocks = BlockSet { option, qualifier };
        head.add_payload_len(blocks.len());
        Self { head, blocks }
    }

    pub fn blocks(&self) -> BlockSet {
        self.blocks.clone()
    }

    pub fn to_vec(&self) -> Vec<u8> {
        let mut data = Vec::with_capacity(self.head.payload_len + 26);
        self.head.append_data(&mut data);
        self.blocks.append_data(&mut data);
        data
    }
}

impl TryFrom<PnDcp> for PacketSetReq {
    type Error = anyhow::Error;

    fn try_from(dcg: PnDcp) -> Result<Self, Self::Error> {
        let PnDcp { head, blocks } = dcg;
        if head.ty != PnDcpTy::SetReq {
            bail!("the packet is pn-dcp, but not  set req!");
        }
        let blocks = BlockSet::try_from(blocks)?;
        Ok(Self { blocks, head })
    }
}

impl TryFrom<&[u8]> for PacketSetReq {
    type Error = anyhow::Error;

    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
        let dcg = PnDcp::try_from(value)?;
        PacketSetReq::try_from(dcg)
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum SetReqBlock {
    Set(BlockSet),
    Padding(BlockPadding),
}

impl BlockTrait for SetReqBlock {
    fn len(&self) -> usize {
        match self {
            Self::Set(a) => a.len(),
            Self::Padding(a) => a.len(),
        }
    }
    fn payload(&self) -> u16 {
        match self {
            Self::Set(a) => a.payload(),
            Self::Padding(a) => a.payload(),
        }
    }

    fn append_data(&self, data: &mut Vec<u8>) {
        match self {
            Self::Padding(a) => a.append_data(data),
            Self::Set(a) => a.append_data(data),
        }
    }
}

#[derive(Debug, Eq, PartialEq, Default)]
#[derefmut(0)]
pub struct SetReqBlocks(pub(crate) Vec<SetReqBlock>);

impl TryFrom<BytesWrap> for SetReqBlocks {
    type Error = anyhow::Error;
    fn try_from(value: BytesWrap) -> Result<Self, Self::Error> {
        let mut index = 0usize;
        let mut blocks = Vec::<SetReqBlock>::new();
        while let Ok(tmp) = value.slice(index..) {
            if tmp.len() == 0 {
                break;
            }
            let block = BlockSet::try_from(tmp)?;
            let len = block.len();
            blocks.push(block.into());
            if len % 2 == 1 {
                blocks.push(BlockPadding.into());
                index += 1;
            }
            index += len;
        }
        Ok(blocks.into())
    }
}