1use crate::error::Error;
15use alloc::vec::Vec;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct PdId {
20 pub vendor_oui: [u8; 3],
22 pub model: u8,
24 pub version: u8,
26 pub serial: u32,
28 pub firmware: [u8; 3],
30}
31
32impl PdId {
33 pub const WIRE_LEN: usize = 12;
35
36 pub fn encode(&self) -> Result<Vec<u8>, Error> {
38 let mut out = Vec::with_capacity(Self::WIRE_LEN);
39 out.extend_from_slice(&self.vendor_oui);
40 out.push(self.model);
41 out.push(self.version);
42 out.extend_from_slice(&self.serial.to_le_bytes());
43 out.extend_from_slice(&self.firmware);
44 Ok(out)
45 }
46
47 pub fn decode(data: &[u8]) -> Result<Self, Error> {
49 if data.len() != Self::WIRE_LEN {
50 return Err(Error::MalformedPayload {
51 code: 0x45,
52 reason: "PDID requires 12 bytes",
53 });
54 }
55 let mut vendor_oui = [0u8; 3];
56 vendor_oui.copy_from_slice(&data[..3]);
57 let mut firmware = [0u8; 3];
58 firmware.copy_from_slice(&data[9..12]);
59 Ok(Self {
60 vendor_oui,
61 model: data[3],
62 version: data[4],
63 serial: u32::from_le_bytes([data[5], data[6], data[7], data[8]]),
64 firmware,
65 })
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn roundtrip() {
75 let id = PdId {
76 vendor_oui: [0x00, 0x06, 0x8E], model: 0x12,
78 version: 0x34,
79 serial: 0xDEAD_BEEF,
80 firmware: [1, 2, 3],
81 };
82 let bytes = id.encode().unwrap();
83 assert_eq!(bytes.len(), 12);
84 let parsed = PdId::decode(&bytes).unwrap();
85 assert_eq!(parsed, id);
86 }
87
88 #[test]
89 fn rejects_truncated() {
90 assert!(PdId::decode(&[0; 11]).is_err());
91 assert!(PdId::decode(&[0; 13]).is_err());
92 }
93}