1mod address;
4
5pub use address::{Address, GatewayID, InvalidGatewayID};
6
7mod crc;
8
9mod escaping;
10mod receive;
11pub use receive::{Counters, Receiver, Sink};
12
13#[derive(Debug, Clone, Eq, PartialEq)]
15pub struct Frame {
16 pub address: Address,
17 pub frame_type: Type,
18 pub payload: Vec<u8>,
19}
20
21impl Frame {
22 pub fn encode(&self) -> Vec<u8> {
25 let start = match self.address {
26 Address::From(_) => [0xff, 0x7e, 0x07].as_slice(),
27 Address::To(_) => [0x00, 0xff, 0xff, 0x7e, 0x07].as_slice(),
28 };
29 let end = &[0x7e, 0x08];
30
31 let mut output_buffer = Vec::with_capacity(
32 start.len()
33 + 4 + 4 + escaping::escaped_length(&self.payload)
36 + 4 + end.len(), );
39 let initial_output_buffer_capacity = output_buffer.capacity();
40
41 output_buffer.extend_from_slice(start);
43
44 let mut body = Vec::with_capacity(2 + 2 + self.payload.len() + 2);
46 let initial_body_capacity = body.capacity();
47 body.extend_from_slice(&<[u8; 2]>::from(self.address));
48 body.extend_from_slice(&self.frame_type.0.to_be_bytes());
49 body.extend_from_slice(&self.payload);
50
51 let crc = crc::crc(&body);
53 body.extend_from_slice(&crc.to_le_bytes());
54
55 escaping::escape(&body, &mut output_buffer);
57
58 output_buffer.extend_from_slice(end);
60
61 debug_assert_eq!(body.capacity(), initial_body_capacity);
63 debug_assert_eq!(output_buffer.capacity(), initial_output_buffer_capacity);
64
65 debug_assert_eq!(body.len(), initial_body_capacity);
67 debug_assert!(initial_output_buffer_capacity <= output_buffer.len() + 6);
68
69 output_buffer
70 }
71}
72
73#[derive(Copy, Clone, Eq, PartialEq)]
75pub struct Type(pub u16);
76impl Type {
77 pub const RECEIVE_REQUEST: Self = Type(0x0148);
78 pub const RECEIVE_RESPONSE: Self = Type(0x0149);
79 pub const COMMAND_REQUEST: Self = Type(0x0B0F);
80 pub const COMMAND_RESPONSE: Self = Type(0x0B10);
81 pub const PING_REQUEST: Self = Type(0x0B00);
82 pub const PING_RESPONSE: Self = Type(0x0B01);
83 pub const ENUMERATION_START_REQUEST: Self = Type(0x0014);
84 pub const ENUMERATION_START_RESPONSE: Self = Type(0x0015);
85 pub const ENUMERATION_REQUEST: Self = Type(0x0038);
86 pub const ENUMERATION_RESPONSE: Self = Type(0x0039);
87 pub const ASSIGN_GATEWAY_ID_REQUEST: Self = Type(0x003C);
88 pub const ASSIGN_GATEWAY_ID_RESPONSE: Self = Type(0x003D);
89 pub const IDENTIFY_REQUEST: Self = Type(0x003A);
90 pub const IDENTIFY_RESPONSE: Self = Type(0x003B);
91 pub const VERSION_REQUEST: Self = Type(0x000A);
92 pub const VERSION_RESPONSE: Self = Type(0x000B);
93 pub const ENUMERATION_END_REQUEST: Self = Type(0x0E02);
94 pub const ENUMERATION_END_RESPONSE: Self = Type(0x0006);
95}
96
97impl std::fmt::Debug for Type {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 match *self {
100 Self::RECEIVE_REQUEST => f.write_str("Type::RECEIVE_REQUEST"),
101 Self::RECEIVE_RESPONSE => f.write_str("Type::RECEIVE_RESPONSE"),
102 Self::COMMAND_REQUEST => f.write_str("Type::COMMAND_REQUEST"),
103 Self::COMMAND_RESPONSE => f.write_str("Type::COMMAND_RESPONSE"),
104 Self::PING_REQUEST => f.write_str("Type::PING_REQUEST"),
105 Self::PING_RESPONSE => f.write_str("Type::PING_RESPONSE"),
106 Self::ENUMERATION_START_REQUEST => f.write_str("Type::ENUMERATION_START_REQUEST"),
107 Self::ENUMERATION_START_RESPONSE => f.write_str("Type::ENUMERATION_START_RESPONSE"),
108 Self::ENUMERATION_REQUEST => f.write_str("Type::ENUMERATION_REQUEST"),
109 Self::ENUMERATION_RESPONSE => f.write_str("Type::ENUMERATION_RESPONSE"),
110 Self::ASSIGN_GATEWAY_ID_REQUEST => f.write_str("Type::ASSIGN_GATEWAY_ID_REQUEST"),
111 Self::ASSIGN_GATEWAY_ID_RESPONSE => f.write_str("Type::ASSIGN_GATEWAY_ID_RESPONSE"),
112 Self::IDENTIFY_REQUEST => f.write_str("Type::IDENTIFY_REQUEST"),
113 Self::IDENTIFY_RESPONSE => f.write_str("Type::IDENTIFY_RESPONSE"),
114 Self::VERSION_REQUEST => f.write_str("Type::VERSION_REQUEST"),
115 Self::VERSION_RESPONSE => f.write_str("Type::VERSION_RESPONSE"),
116 Self::ENUMERATION_END_REQUEST => f.write_str("Type::ENUMERATION_END_REQUEST"),
117 Self::ENUMERATION_END_RESPONSE => f.write_str("Type::ENUMERATION_END_RESPONSE"),
118 Self(value) => f
119 .debug_tuple("Type")
120 .field(&format_args!("{:#04x}", value))
121 .finish(),
122 }
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[test]
131 fn frame_encoding() {
132 let encoded = Frame {
133 address: Address::From(GatewayID::try_from(0x1201).unwrap()),
134 frame_type: Type(0x0149),
135 payload: b"\x00\xFF\x7C\xDB\xC2".as_slice().into(),
136 }
137 .encode();
138
139 assert_eq!(
140 encoded.as_slice(),
141 [
142 0xFF, 0x7E, 0x07, 0x92, 0x01, 0x01, 0x49, 0x00, 0xFF, 0x7C, 0xDB, 0xC2, 0x7E, 0x05,
143 0x85, 0x7E, 0x08
144 ]
145 .as_slice()
146 );
147
148 assert!(encoded.capacity() <= encoded.len() + 6);
149 }
150
151 #[test]
152 fn type_debug() {
153 assert_eq!(
154 format!("{:?}", &Type::RECEIVE_RESPONSE),
155 "Type::RECEIVE_RESPONSE"
156 );
157 assert_eq!(format!("{:?}", &Type(0x1234)), "Type(0x1234)");
158 }
159}