pn_dcp/packet/
set_resp.rs

1use crate::block::{BlockPadding, BlockResp, BlockTrait};
2use crate::comm::BytesWrap;
3use crate::options::{BlockError, OptionAndSub};
4use crate::packet::{DcpHead, PnDcp, PnDcpTy};
5use anyhow::bail;
6use pn_dcp_macro::derefmut;
7use pnet::datalink::MacAddr;
8use std::ops::{Deref, DerefMut};
9
10#[derive(Debug, Eq, PartialEq, Clone)]
11#[derefmut(head)]
12pub struct PacketSetResp {
13    head: DcpHead,
14    blocks: SetRespBlocks,
15}
16impl Deref for PacketSetResp {
17    type Target = DcpHead;
18
19    fn deref(&self) -> &Self::Target {
20        &self.head
21    }
22}
23#[derive(Default, Debug, Eq, PartialEq, Clone)]
24#[derefmut(0)]
25pub struct SetRespBlocks(pub(crate) Vec<SetRespBlock>);
26
27impl TryFrom<BytesWrap> for SetRespBlocks {
28    type Error = anyhow::Error;
29    fn try_from(value: BytesWrap) -> Result<Self, Self::Error> {
30        let mut index = 0usize;
31        let mut blocks = Vec::<SetRespBlock>::new();
32        while let Ok(tmp) = value.slice(index..) {
33            if tmp.len() == 0 {
34                break;
35            }
36            let option = BlockResp::try_from(tmp.clone())?;
37            let len = option.len();
38            blocks.push(option.into());
39            if len % 2 == 1 {
40                blocks.push(BlockPadding.into());
41                index += 1;
42            }
43            index += len;
44        }
45        Ok(blocks.into())
46    }
47}
48
49impl BlockTrait for SetRespBlocks {
50    fn len(&self) -> usize {
51        let mut len = 0;
52        for block in &self.0 {
53            len += block.len();
54        }
55        len
56    }
57
58    fn payload(&self) -> u16 {
59        unreachable!()
60    }
61
62    fn append_data(&self, data: &mut Vec<u8>) {
63        for block in &self.0 {
64            block.append_data(data)
65        }
66    }
67}
68
69#[derive(Debug, Eq, PartialEq, Clone)]
70pub enum SetRespBlock {
71    Response(BlockResp),
72    Padding(BlockPadding),
73}
74
75impl BlockTrait for SetRespBlock {
76    fn len(&self) -> usize {
77        match self {
78            Self::Response(a) => a.len(),
79            Self::Padding(a) => a.len(),
80        }
81    }
82    fn payload(&self) -> u16 {
83        match self {
84            Self::Response(a) => a.payload(),
85            Self::Padding(a) => a.payload(),
86        }
87    }
88
89    fn append_data(&self, data: &mut Vec<u8>) {
90        match self {
91            Self::Padding(a) => a.append_data(data),
92            Self::Response(a) => a.append_data(data),
93        }
94    }
95}
96
97impl PacketSetResp {
98    pub fn new(source: MacAddr, dest: MacAddr, option: OptionAndSub, error: BlockError) -> Self {
99        let head = DcpHead::new(dest, source, PnDcpTy::SetRespSuc);
100        let blocks = BlockResp(option, error);
101        let mut resp = Self {
102            head,
103            blocks: SetRespBlocks::default(),
104        };
105        resp.append_block(blocks);
106        resp
107    }
108    fn append_block(&mut self, block: impl Into<SetRespBlock>) {
109        let block = block.into();
110        let block_len = block.len();
111        self.blocks.0.push(block);
112        self.head.add_payload_len(block_len);
113        if block_len % 2 == 1 {
114            self.blocks.0.push(SetRespBlock::Padding(BlockPadding));
115            self.head.add_payload_len(1);
116        }
117    }
118
119    pub fn blocks(&self) -> Vec<BlockResp> {
120        let mut blocks = Vec::new();
121        for block in self.blocks.iter() {
122            if let SetRespBlock::Response(common) = block {
123                blocks.push(common.clone());
124            }
125        }
126        blocks
127    }
128
129    pub fn to_vec(&self) -> Vec<u8> {
130        let mut data = Vec::with_capacity(self.head.payload_len + 26);
131        self.head.append_data(&mut data);
132        self.blocks.append_data(&mut data);
133        data
134    }
135}
136
137impl TryFrom<PnDcp> for PacketSetResp {
138    type Error = anyhow::Error;
139
140    fn try_from(dcg: PnDcp) -> Result<Self, Self::Error> {
141        let PnDcp { head, blocks } = dcg;
142        if head.ty != PnDcpTy::SetRespSuc {
143            bail!("the packet is pn-dcp, but not set resp success!");
144        }
145        let blocks = SetRespBlocks::try_from(blocks)?;
146        Ok(Self { blocks, head })
147    }
148}
149
150impl TryFrom<&[u8]> for PacketSetResp {
151    type Error = anyhow::Error;
152
153    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
154        let dcg = PnDcp::try_from(value)?;
155        PacketSetResp::try_from(dcg)
156    }
157}