1use crate::consts::RDM_STATUS_MESSAGE_SIZE;
2use crate::pids;
3use crate::rdm_types::{
4 DeserializationError, DmxStartAddress, StatusMessage, StatusMessages, SupportedParameters,
5};
6use crate::types::DataPack;
7
8pub fn deserialize_identify(buffer: &[u8]) -> Result<bool, DeserializationError> {
9 if buffer.len() != 1 {
10 return Err(DeserializationError);
11 }
12
13 Ok(buffer[0] != 0)
14}
15
16pub fn deserialize_software_version_label(
17 buffer: &[u8],
18) -> Result<heapless::String<32>, DeserializationError> {
19 heapless::String::from_utf8(
20 heapless::Vec::<_, 32>::from_slice(buffer).or(Err(DeserializationError))?,
21 )
22 .or(Err(DeserializationError))
23}
24
25pub fn deserialize_status_messages(buffer: &[u8]) -> Result<StatusMessages, DeserializationError> {
26 if buffer.len() % RDM_STATUS_MESSAGE_SIZE != 0 {
27 return Err(DeserializationError);
28 }
29
30 let mut status_messages = heapless::Vec::new();
31 for package_bytes in buffer.chunks(RDM_STATUS_MESSAGE_SIZE) {
32 status_messages
33 .push(StatusMessage::deserialize(package_bytes)?)
34 .map_err(|_| DeserializationError)?;
35 }
36
37 Ok(status_messages)
38}
39
40pub fn deserialize_supported_parameters(
41 buffer: &[u8],
42) -> Result<SupportedParameters, DeserializationError> {
43 if buffer.len() % 2 != 0 {
44 return Err(DeserializationError);
45 }
46
47 let mut supported_parameters = heapless::Vec::new();
48 for package_bytes in buffer.chunks(2) {
49 supported_parameters
50 .push(u16::from_be_bytes(package_bytes.try_into().unwrap()))
51 .map_err(|_| DeserializationError)?;
52 }
53
54 Ok(supported_parameters)
55}
56
57#[derive(Debug)]
58pub struct RdmResponseInfo {
59 pub parameter_id: u16,
60 pub message_count: u8,
61 pub data: DataPack,
62}
63
64#[derive(Debug)]
65pub enum RdmResponsePackage {
66 IdentifyDevice(bool),
67 SoftwareVersionLabel(heapless::String<32>),
68 DmxStartAddress(DmxStartAddress),
69 StatusMessages(StatusMessages),
70 SupportedParameters(SupportedParameters),
71 Custom(RdmResponseInfo),
72}
73
74impl RdmResponsePackage {
75 pub fn from_response_info(
76 response_info: RdmResponseInfo,
77 ) -> Result<Self, DeserializationError> {
78 Ok(match response_info.parameter_id {
79 pids::IDENTIFY_DEVICE => {
80 RdmResponsePackage::IdentifyDevice(deserialize_identify(&response_info.data)?)
81 },
82 pids::SOFTWARE_VERSION_LABEL => RdmResponsePackage::SoftwareVersionLabel(
83 deserialize_software_version_label(&response_info.data)?,
84 ),
85 pids::DMX_START_ADDRESS => RdmResponsePackage::DmxStartAddress(
86 DmxStartAddress::deserialize(&response_info.data)?,
87 ),
88 pids::STATUS_MESSAGES => RdmResponsePackage::StatusMessages(
89 deserialize_status_messages(&response_info.data)?,
90 ),
91 pids::SUPPORTED_PARAMETERS => RdmResponsePackage::SupportedParameters(
92 deserialize_supported_parameters(&response_info.data)?,
93 ),
94 _ => Self::Custom(response_info),
95 })
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use crate::rdm_packages::deserialize_identify;
102
103 #[test]
104 fn test_deserialize_identify_success() {
105 assert_eq!(deserialize_identify(&[0]).unwrap(), false);
106 assert_eq!(deserialize_identify(&[1]).unwrap(), true);
107
108 assert_eq!(deserialize_identify(&[3]).unwrap(), true);
110 }
111
112 #[test]
113 fn test_deserialize_identify_failure() {
114 deserialize_identify(&[2, 1]).unwrap_err();
115 deserialize_identify(&[0, 0]).unwrap_err();
116 }
117}