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