1use crate::caps::{Capability, FunctionCode};
8use crate::error::Error;
9use alloc::vec::Vec;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct PdCap {
14 pub capabilities: Vec<Capability>,
16}
17
18impl PdCap {
19 pub fn new(capabilities: Vec<Capability>) -> Self {
21 Self { capabilities }
22 }
23
24 pub fn capability(&self, code: FunctionCode) -> Option<Capability> {
26 self.capabilities
27 .iter()
28 .copied()
29 .find(|c| c.code == code.as_byte())
30 }
31
32 pub fn encode(&self) -> Result<Vec<u8>, Error> {
34 let mut out = Vec::with_capacity(self.capabilities.len() * Capability::WIRE_LEN);
35 for c in &self.capabilities {
36 out.extend_from_slice(&c.encode());
37 }
38 Ok(out)
39 }
40
41 pub fn decode(data: &[u8]) -> Result<Self, Error> {
43 if data.len() % Capability::WIRE_LEN != 0 {
44 return Err(Error::MalformedPayload {
45 code: 0x46,
46 reason: "PDCAP payload must be multiple of 3 bytes",
47 });
48 }
49 let capabilities = data
50 .chunks_exact(Capability::WIRE_LEN)
51 .map(|c| Capability::decode([c[0], c[1], c[2]]))
52 .collect();
53 Ok(Self { capabilities })
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn lookup_function_code() {
63 let body = PdCap::new(alloc::vec![
64 Capability {
65 code: FunctionCode::CommunicationSecurity.as_byte(),
66 compliance: 1,
67 number_of: 1,
68 },
69 Capability {
70 code: FunctionCode::ReceiveBufferSize.as_byte(),
71 compliance: 0x80,
72 number_of: 0,
73 },
74 ]);
75 let aes = body
76 .capability(FunctionCode::CommunicationSecurity)
77 .unwrap();
78 assert_eq!(aes.compliance, 1);
79 let rxsize = body.capability(FunctionCode::ReceiveBufferSize).unwrap();
80 assert_eq!(rxsize.u16_value(), 128);
81 }
82
83 #[test]
84 fn roundtrip() {
85 let body = PdCap::new(alloc::vec![
86 Capability {
87 code: 1,
88 compliance: 1,
89 number_of: 4
90 },
91 Capability {
92 code: 2,
93 compliance: 1,
94 number_of: 2
95 },
96 ]);
97 let bytes = body.encode().unwrap();
98 assert_eq!(bytes, [1, 1, 4, 2, 1, 2]);
99 let parsed = PdCap::decode(&bytes).unwrap();
100 assert_eq!(parsed, body);
101 }
102}