1use super::{
2 get_key_length, get_num_grave_goods, get_num_last_will, get_num_protocol_versions,
3 get_path_length, get_request_pattern_length, get_value_length,
4};
5use crate::{
6 error::EncodeResult, prepend_buffer_length, ClientMessage, Export, Get, HandshakeRequest,
7 Import, KeyValuePair, PGet, PSubscribe, ProtocolVersion, Set, Subscribe, Unsubscribe, EXP, GET,
8 HSHKR, IMP, PGET, PSUB, SET, SUB, USUB,
9};
10
11pub fn encode_message(msg: &ClientMessage) -> EncodeResult<Vec<u8>> {
12 match msg {
13 ClientMessage::HandshakeRequest(msg) => encode_handshake_request_message(msg),
14 ClientMessage::Get(msg) => encode_get_message(msg),
15 ClientMessage::PGet(msg) => encode_pget_message(msg),
16 ClientMessage::Set(msg) => encode_set_message(msg),
17 ClientMessage::Subscribe(msg) => encode_subscribe_message(msg),
18 ClientMessage::PSubscribe(msg) => encode_psubscribe_message(msg),
19 ClientMessage::Export(msg) => encode_export_message(msg),
20 ClientMessage::Import(msg) => encode_import_message(msg),
21 ClientMessage::Unsubscribe(msg) => encode_unsubscribe_message(msg),
22 }
23}
24
25pub fn encode_get_message(msg: &Get) -> EncodeResult<Vec<u8>> {
26 let key_length = get_key_length(&msg.key)?;
27
28 let mut buf = vec![GET];
29
30 buf.extend(msg.transaction_id.to_be_bytes());
31 buf.extend(key_length.to_be_bytes());
32 buf.extend(msg.key.as_bytes());
33
34 prepend_buffer_length(buf)
35}
36
37pub fn encode_pget_message(msg: &PGet) -> EncodeResult<Vec<u8>> {
38 let request_pattern_length = get_request_pattern_length(&msg.request_pattern)?;
39
40 let mut buf = vec![PGET];
41
42 buf.extend(msg.transaction_id.to_be_bytes());
43 buf.extend(request_pattern_length.to_be_bytes());
44 buf.extend(msg.request_pattern.as_bytes());
45
46 prepend_buffer_length(buf)
47}
48
49pub fn encode_set_message(msg: &Set) -> EncodeResult<Vec<u8>> {
50 let key_length = get_key_length(&msg.key)?;
51 let value_length = get_value_length(&msg.value)?;
52
53 let mut buf = vec![SET];
54
55 buf.extend(msg.transaction_id.to_be_bytes());
56 buf.extend(key_length.to_be_bytes());
57 buf.extend(value_length.to_be_bytes());
58 buf.extend(msg.key.as_bytes());
59 buf.extend(msg.value.as_bytes());
60
61 prepend_buffer_length(buf)
62}
63
64pub fn encode_subscribe_message(msg: &Subscribe) -> EncodeResult<Vec<u8>> {
65 let key_length = get_key_length(&msg.key)?;
66
67 let mut buf = vec![SUB];
68
69 buf.extend(msg.transaction_id.to_be_bytes());
70 buf.extend(key_length.to_be_bytes());
71 buf.extend(msg.key.as_bytes());
72 buf.push(if msg.unique { 1 } else { 0 });
73
74 prepend_buffer_length(buf)
75}
76
77pub fn encode_psubscribe_message(msg: &PSubscribe) -> EncodeResult<Vec<u8>> {
78 let request_pattern_length = get_request_pattern_length(&msg.request_pattern)?;
79
80 let mut buf = vec![PSUB];
81
82 buf.extend(msg.transaction_id.to_be_bytes());
83 buf.extend(request_pattern_length.to_be_bytes());
84 buf.extend(msg.request_pattern.as_bytes());
85 buf.push(if msg.unique { 1 } else { 0 });
86
87 prepend_buffer_length(buf)
88}
89
90pub fn encode_export_message(msg: &Export) -> EncodeResult<Vec<u8>> {
91 let path_length = get_path_length(&msg.path)?;
92
93 let mut buf = vec![EXP];
94
95 buf.extend(msg.transaction_id.to_be_bytes());
96 buf.extend(path_length.to_be_bytes());
97 buf.extend(msg.path.as_bytes());
98
99 prepend_buffer_length(buf)
100}
101
102pub fn encode_import_message(msg: &Import) -> EncodeResult<Vec<u8>> {
103 let path_length = get_path_length(&msg.path)?;
104
105 let mut buf = vec![IMP];
106
107 buf.extend(msg.transaction_id.to_be_bytes());
108 buf.extend(path_length.to_be_bytes());
109 buf.extend(msg.path.as_bytes());
110
111 prepend_buffer_length(buf)
112}
113
114pub fn encode_unsubscribe_message(msg: &Unsubscribe) -> EncodeResult<Vec<u8>> {
115 let mut buf = vec![USUB];
116
117 buf.extend(msg.transaction_id.to_be_bytes());
118
119 prepend_buffer_length(buf)
120}
121
122pub fn encode_handshake_request_message(msg: &HandshakeRequest) -> EncodeResult<Vec<u8>> {
123 let num_protocol_versions = get_num_protocol_versions(&msg.supported_protocol_versions)?;
124 let num_last_will = get_num_last_will(&msg.last_will)?;
125 let num_grave_goods = get_num_grave_goods(&msg.grave_goods)?;
126
127 let mut buf = vec![HSHKR];
128
129 buf.extend(num_protocol_versions.to_be_bytes());
130 buf.extend(num_last_will.to_be_bytes());
131 buf.extend(num_grave_goods.to_be_bytes());
132
133 for ProtocolVersion { major, minor } in &msg.supported_protocol_versions {
134 buf.extend(major.to_be_bytes());
135 buf.extend(minor.to_be_bytes());
136 }
137
138 for KeyValuePair { key, value } in &msg.last_will {
139 let key_length = get_key_length(&key)?;
140 let value_length = get_value_length(&value)?;
141 buf.extend(key_length.to_be_bytes());
142 buf.extend(value_length.to_be_bytes());
143 }
144
145 for grave_good in &msg.grave_goods {
146 let key_length = get_key_length(&grave_good)?;
147 buf.extend(key_length.to_be_bytes());
148 }
149
150 for KeyValuePair { key, value } in &msg.last_will {
151 buf.extend(key.as_bytes());
152 buf.extend(value.as_bytes());
153 }
154
155 for grave_good in &msg.grave_goods {
156 buf.extend(grave_good.as_bytes());
157 }
158
159 prepend_buffer_length(buf)
160}
161
162#[cfg(test)]
163mod test {
164 use super::*;
165 use crate::{
166 Export, Get, Import, PGet, PSubscribe, Set, Subscribe, Unsubscribe, EXP, GET, IMP, PGET,
167 PSUB, SET, SUB, USUB,
168 };
169
170 #[test]
171 fn get_message_is_encoded_correctly() {
172 let msg = Get {
173 transaction_id: 4,
174 key: "trolo".to_owned(),
175 };
176
177 let data = [
178 0b00000000, 0b00000000, 0b00000000, 0b00010000, GET, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
180 0b00000000, 0b00000100, 0b00000000, 0b00000101, b't', b'r', b'o', b'l', b'o',
181 ];
182
183 assert_eq!(data.to_vec(), encode_get_message(&msg).unwrap());
184 }
185
186 #[test]
187 fn pget_message_is_encoded_correctly() {
188 let msg = PGet {
189 transaction_id: 4,
190 request_pattern: "trolo".to_owned(),
191 };
192
193 let data = [
194 0b00000000, 0b00000000, 0b00000000, 0b00010000, PGET, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
196 0b00000000, 0b00000100, 0b00000000, 0b00000101, b't', b'r', b'o', b'l', b'o',
197 ];
198
199 assert_eq!(data.to_vec(), encode_pget_message(&msg).unwrap());
200 }
201
202 #[test]
203 fn set_message_is_encoded_correctly() {
204 let msg = Set {
205 transaction_id: 0,
206 key: "yo/mama".to_owned(),
207 value: "fat".to_owned(),
208 };
209
210 let data = [
211 0b00000000, 0b00000000, 0b00000000, 0b00011001, SET, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
213 0b00000000, 0b00000000, 0b00000000, 0b00000111, 0b00000000, 0b00000000, 0b00000000,
214 0b00000011, b'y', b'o', b'/', b'm', b'a', b'm', b'a', b'f', b'a', b't',
215 ];
216
217 assert_eq!(data.to_vec(), encode_set_message(&msg).unwrap());
218 }
219
220 #[test]
221 fn subscribe_message_is_encoded_correctly() {
222 let msg = Subscribe {
223 transaction_id: 5536684732567,
224 key: "let/me/?/you/its/features".to_owned(),
225 unique: true,
226 };
227
228 let data = [
229 0b00000000, 0b00000000, 0b00000000, 0b00100101, SUB, 0b00000000, 0b00000000, 0b00000101, 0b00001001, 0b00011100, 0b00100000,
231 0b01110000, 0b10010111, 0b00000000, 0b00011001, b'l', b'e', b't', b'/', b'm', b'e',
232 b'/', b'?', b'/', b'y', b'o', b'u', b'/', b'i', b't', b's', b'/', b'f', b'e', b'a',
233 b't', b'u', b'r', b'e', b's', 0b00000001,
234 ];
235
236 assert_eq!(data.to_vec(), encode_subscribe_message(&msg).unwrap());
237 }
238
239 #[test]
240 fn psubscribe_message_is_encoded_correctly() {
241 let msg = PSubscribe {
242 transaction_id: 5536684732567,
243 request_pattern: "let/me/?/you/its/features".to_owned(),
244 unique: false,
245 };
246
247 let data = [
248 0b00000000, 0b00000000, 0b00000000, 0b00100101, PSUB, 0b00000000, 0b00000000, 0b00000101, 0b00001001, 0b00011100, 0b00100000,
250 0b01110000, 0b10010111, 0b00000000, 0b00011001, b'l', b'e', b't', b'/', b'm', b'e',
251 b'/', b'?', b'/', b'y', b'o', b'u', b'/', b'i', b't', b's', b'/', b'f', b'e', b'a',
252 b't', b'u', b'r', b'e', b's', 0b00000000,
253 ];
254
255 assert_eq!(data.to_vec(), encode_psubscribe_message(&msg).unwrap());
256 }
257
258 #[test]
259 fn export_message_is_encoded_correctly() {
260 let msg = Export {
261 transaction_id: 42,
262 path: "/path/to/file".to_owned(),
263 };
264
265 let data = [
266 0b00000000, 0b00000000, 0b00000000, 0b00011000, EXP, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
268 0b00000000, 0b00101010, 0b00000000, 0b00001101, b'/', b'p', b'a', b't', b'h', b'/',
269 b't', b'o', b'/', b'f', b'i', b'l', b'e',
270 ];
271
272 assert_eq!(data.to_vec(), encode_export_message(&msg).unwrap());
273 }
274
275 #[test]
276 fn import_message_is_encoded_correctly() {
277 let msg = Import {
278 transaction_id: 42,
279 path: "/path/to/file".to_owned(),
280 };
281
282 let data = [
283 0b00000000, 0b00000000, 0b00000000, 0b00011000, IMP, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
285 0b00000000, 0b00101010, 0b00000000, 0b00001101, b'/', b'p', b'a', b't', b'h', b'/',
286 b't', b'o', b'/', b'f', b'i', b'l', b'e',
287 ];
288
289 assert_eq!(data.to_vec(), encode_import_message(&msg).unwrap());
290 }
291
292 #[test]
293 fn unsubscribe_message_is_encoded_correctly() {
294 let msg = Unsubscribe { transaction_id: 42 };
295
296 let data = [
297 0b00000000, 0b00000000, 0b00000000, 0b00001001, USUB, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
299 0b00000000, 0b00101010,
300 ];
301
302 assert_eq!(data.to_vec(), encode_unsubscribe_message(&msg).unwrap());
303 }
304
305 #[test]
306 fn handshake_request_message_is_encoded_correctly() {
307 let msg = HandshakeRequest {
308 supported_protocol_versions: vec![
309 ProtocolVersion { major: 0, minor: 1 },
310 ProtocolVersion { major: 0, minor: 5 },
311 ProtocolVersion { major: 1, minor: 0 },
312 ],
313 last_will: vec![("last/will", "test").into()],
314 grave_goods: vec!["grave/goods/1".into(), "grave/goods/2".into()],
315 };
316
317 let data = [
318 0b00000000, 0b00000000, 0b00000000, 0b01000001, HSHKR, 0b00000011, 0b00000001, 0b00000010, 0b00000000, 0b00000000, 0b00000000, 0b00000001, 0b00000000, 0b00000000, 0b00000000, 0b00000101, 0b00000000, 0b00000001, 0b00000000, 0b00000000, 0b00000000, 0b00001001, 0b00000000, 0b00000000, 0b00000000, 0b00000100, 0b00000000, 0b00001101, 0b00000000, 0b00001101, b'l', b'a', b's', b't', b'/', b'w', b'i', b'l', b'l', b't', b'e', b's', b't', b'g', b'r', b'a', b'v', b'e', b'/', b'g', b'o', b'o', b'd', b's', b'/',
333 b'1', b'g', b'r', b'a', b'v', b'e', b'/', b'g', b'o', b'o', b'd', b's', b'/',
335 b'2', ];
337
338 assert_eq!(
339 data.to_vec(),
340 encode_handshake_request_message(&msg).unwrap()
341 );
342 }
343}