1use umsh_core::{PacketType, PayloadType};
2
3use crate::{AppParseError, MacCommand, NodeIdentityPayload, mac_command};
4
5pub fn split_payload_type(payload: &[u8]) -> Result<(PayloadType, &[u8]), AppParseError> {
6 if payload.is_empty() {
7 return Ok((PayloadType::Empty, &[]));
8 }
9 if let Some(payload_type) = PayloadType::from_byte(payload[0]) {
10 Ok((payload_type, &payload[1..]))
11 } else {
12 Ok((PayloadType::Empty, payload))
13 }
14}
15
16pub fn expect_payload_type(
17 packet_type: PacketType,
18 payload: &[u8],
19 expected: PayloadType,
20) -> Result<&[u8], AppParseError> {
21 let (payload_type, body) = split_payload_type(payload)?;
22 if !payload_type.allowed_for(packet_type) {
23 return Err(AppParseError::PayloadTypeNotAllowed {
24 payload_type: payload_type as u8,
25 packet_type,
26 });
27 }
28 if payload_type != expected {
29 return Err(AppParseError::InvalidPayloadType(payload_type as u8));
30 }
31 Ok(body)
32}
33
34pub fn parse_mac_command_payload(
35 packet_type: PacketType,
36 payload: &[u8],
37) -> Result<MacCommand<'_>, AppParseError> {
38 mac_command::parse(expect_payload_type(
39 packet_type,
40 payload,
41 PayloadType::MacCommand,
42 )?)
43}
44
45pub fn parse_node_identity_payload(
46 packet_type: PacketType,
47 payload: &[u8],
48) -> Result<NodeIdentityPayload, AppParseError> {
49 NodeIdentityPayload::from_bytes(expect_payload_type(
50 packet_type,
51 payload,
52 PayloadType::NodeIdentity,
53 )?)
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
63 fn split_empty_gives_empty_type() {
64 let (ty, body) = split_payload_type(&[]).unwrap();
65 assert_eq!(ty, PayloadType::Empty);
66 assert_eq!(body, &[] as &[u8]);
67 }
68
69 #[test]
70 fn split_unknown_byte_gives_empty_type_with_full_slice() {
71 let payload = &[0x99u8, 0x01, 0x02];
73 let (ty, body) = split_payload_type(payload).unwrap();
74 assert_eq!(ty, PayloadType::Empty);
75 assert_eq!(body, payload);
76 }
77
78 #[test]
79 fn split_known_byte_strips_type_prefix() {
80 let payload = &[0x02u8, 0xAA, 0xBB];
82 let (ty, body) = split_payload_type(payload).unwrap();
83 assert_eq!(ty, PayloadType::MacCommand);
84 assert_eq!(body, &[0xAAu8, 0xBB]);
85 }
86
87 #[test]
90 fn expect_correct_type_returns_body() {
91 let payload = &[0x02u8, 0x01]; let body = expect_payload_type(PacketType::Unicast, payload, PayloadType::MacCommand).unwrap();
94 assert_eq!(body, &[0x01u8]);
95 }
96
97 #[test]
98 fn expect_wrong_type_returns_invalid_payload_type() {
99 let payload = &[0x01u8, 0x02, 0x00];
101 let err = expect_payload_type(PacketType::Unicast, payload, PayloadType::MacCommand)
102 .unwrap_err();
103 assert!(matches!(err, AppParseError::InvalidPayloadType(0x01)));
104 }
105
106 #[test]
107 fn expect_disallowed_for_packet_type_returns_error() {
108 let payload = &[0x02u8, 0x01];
110 let err =
111 expect_payload_type(PacketType::Broadcast, payload, PayloadType::MacCommand)
112 .unwrap_err();
113 assert!(matches!(err, AppParseError::PayloadTypeNotAllowed { .. }));
114 }
115}