1use std::{
2 borrow::Cow,
3 convert::TryFrom,
4 io::{Cursor, Read},
5};
6
7use byteorder::{ByteOrder, LittleEndian, ReadBytesExt as _};
8use log;
9
10use crate::{
11 bytes::{BufMut, Bytes, BytesMut},
12 frame::*,
13 header::RequestHeader,
14 Error,
15};
16pub mod tcp;
17
18#[inline]
20pub fn bools_to_bytes(bools: &[bool]) -> Vec<u8> {
21 let capacity = (bools.len() + 1) / 2;
22 let mut result = Vec::with_capacity(capacity);
23
24 let chunks = bools.chunks_exact(2);
25 let remainder = chunks.remainder();
26
27 for chunk in chunks {
29 result.push((chunk[0] as u8) << 4 | (chunk[1] as u8));
30 }
31
32 if !remainder.is_empty() {
34 result.push((remainder[0] as u8) << 4);
35 }
36
37 result
38}
39
40#[inline]
42pub fn bytes_to_bools(bytes: &[u8]) -> Vec<bool> {
43 let mut result = Vec::with_capacity(bytes.len() * 2);
44 for &byte in bytes {
45 result.push((byte >> 4) & 0x01 != 0);
46 result.push(byte & 0x01 != 0);
47 }
48 result
49}
50pub struct ClientEncoder;
52
53pub struct ServerDecoder;
55
56pub struct ClientDecoder;
58
59impl ClientEncoder {
60 pub fn encode<'a>(req: Request<'a>) -> Result<Vec<Bytes>, Error> {
62 Vec::try_from(req)
64 }
65}
66
67impl ServerDecoder {
68 pub fn decode(bytes: Bytes) -> Result<Request<'static>, Error> {
70 Request::try_from(bytes)
72 }
73}
74
75impl ClientDecoder {
76 pub fn decode(bytes: Vec<Bytes>, req: Request<'_>) -> Result<Response, Error> {
78 Response::try_from((bytes, req))
80 }
81}
82
83impl<'a> TryFrom<Request<'a>> for Vec<Bytes> {
85 type Error = Error;
86
87 fn try_from(req: Request<'a>) -> Result<Vec<Bytes>, Error> {
88 use crate::frame::Request::*;
89
90 let (address, quantity_or_len, write_cursor) = match req {
91 ReadU8s(ref address, quantity) => (address.clone(), quantity, None),
92 WriteU8s(ref address, ref u8s) => {
93 let cursor = Cursor::new(Cow::Owned(u8s.to_vec()));
94 (
95 address.clone(),
96 ((u8s.len() as f32) / 2.0).round() as u32,
97 Some(WriteCursor::U8s(cursor)),
98 )
99 }
100 ReadBits(ref address, quantity) => (address.clone(), quantity, None),
101 WriteBits(ref address, ref bits) => {
102 let bytes = bools_to_bytes(bits);
103 let cursor = Cursor::new(Cow::Owned(bytes));
104 (
105 address.clone(),
106 bits.len() as u32,
107 Some(WriteCursor::Bits(cursor)),
108 )
109 }
110 };
111
112 enum WriteCursor {
113 U8s(Cursor<Cow<'static, [u8]>>),
114 Bits(Cursor<Cow<'static, [u8]>>),
115 }
116
117 let mut results = Vec::new();
118 let (u32_number, code) = parse_address_and_get_instruction_code(&address)?;
119 let mut current_len = quantity_or_len;
120 let mut current_address = u32_number;
121 let header = RequestHeader::new();
122
123 while current_len > 0 {
124 let len = current_len.min(LIMIT) as u16;
125
126 let mut data = match write_cursor {
127 Some(WriteCursor::U8s(_)) => BytesMut::with_capacity(
128 header.len() + REQUEST_BYTE_LAST_LEN + (len * 2) as usize,
129 ),
130 Some(WriteCursor::Bits(_)) => {
131 BytesMut::with_capacity(header.len() + REQUEST_BYTE_LAST_LEN + len as usize)
132 }
133 None => BytesMut::with_capacity(header.len() + REQUEST_BYTE_LAST_LEN),
134 };
135
136 data.put_slice(header.bytes());
137 data.put_slice(&req.function_code().value());
138 request_command(&mut data, current_address, code, len);
139
140 if let Some(write_cursor) = &write_cursor {
141 match write_cursor {
142 WriteCursor::U8s(cursor) => {
143 let mut write_iter = cursor.get_ref().iter().cloned();
144 for _ in 0..len * 2 {
145 if let Some(value) = write_iter.next() {
146 data.put_u8(value);
147 }
148 }
149 }
150 WriteCursor::Bits(cursor) => {
151 let bytes_data = cursor.get_ref();
153 for &byte_val in bytes_data.iter() {
154 data.put_u8(byte_val);
155 }
156 }
157 }
158 }
159
160 let length = (data.len() - header.len() + 2) as u16;
161 LittleEndian::write_u16(&mut data[header.len() - 4..header.len() - 2], length);
162
163 current_address += len as u32;
164 current_len = current_len.saturating_sub(len as u32);
165 results.push(data.freeze());
166 }
167
168 Ok(results)
169 }
170}
171
172impl TryFrom<(Vec<Bytes>, Request<'_>)> for Response {
174 type Error = Error;
175 fn try_from((bytes, req): (Vec<Bytes>, Request)) -> Result<Self, Error> {
176 log::debug!("=== Client received response from server ===");
177 for (i, byte_chunk) in bytes.iter().enumerate() {
178 log::debug!("Response chunk {}: {:02X?}", i, byte_chunk.as_ref());
179 }
180
181 let mut data = Vec::new();
182
183 for (i, byte) in bytes.iter().enumerate() {
189 data.extend_from_slice(&byte[2..]);
202 }
203
204 log::debug!("Response data after processing: {:02X?}", data);
205
206 let final_rdr = Cursor::new(data);
207
208 match req {
209 Request::ReadU8s(_, _) => Ok(Response::ReadU8s(final_rdr.get_ref().to_vec())),
210 Request::WriteU8s(_, _) => Ok(Response::WriteU8s()),
211 Request::ReadBits(_, _) => {
212 let bytes = final_rdr.get_ref().to_vec();
213 let bits = bytes_to_bools(&bytes);
214 Ok(Response::ReadBits(bits))
215 }
216 Request::WriteBits(_, _) => Ok(Response::WriteBits()),
217 }
218 }
219}
220
221impl<'a> TryFrom<Bytes> for Request<'a> {
231 type Error = Error;
232
233 fn try_from(bytes: Bytes) -> Result<Self, Error> {
234 let mut cursor = Cursor::new(bytes);
235
236 let _len = cursor.read_u16::<LittleEndian>()? as usize;
237
238 cursor.read_u16::<LittleEndian>()?; log::debug!("Cursor data: {:?}", cursor.get_ref());
243
244 let mut instruction_code = [0u8; 4];
245
246 cursor.read_exact(&mut instruction_code)?;
247 let function_code = FunctionCode::new(BytesMut::from(&instruction_code[..]))
248 .ok_or_else(|| Error::Protocol(ProtocolError::InvalidFunctionCode(instruction_code)))?;
249
250 let start_addr = cursor.read_u24::<LittleEndian>()?;
251 let (prefix, number_base) = find_prefix_and_base_by_code(cursor.read_u8()?).unwrap();
252 let quantity = cursor.read_u16::<LittleEndian>()? as u32;
253
254 if quantity > LIMIT {
255 return Err(Error::Protocol(ProtocolError::OutOfRange));
256 }
257
258 log::debug!("Prefix: {}", prefix);
260 log::debug!("Number base: {:?}", number_base);
262
263 let start_addr: String = match number_base {
265 NumberBase::Decimal => format!("{}", start_addr),
266 NumberBase::Hexadecimal => format!("{:X}", start_addr),
267 };
268
269 log::debug!("Start address (string): {}", start_addr);
270
271 let address: Cow<'a, str> = format!("{}{}", prefix, start_addr).into();
272
273 log::debug!("Raw instruction code: {:02X?}", instruction_code);
274 log::debug!("Parsed function code: {:?}", function_code);
275 log::debug!("Start address: {}", address);
276 log::debug!("Raw quantity: {}", quantity);
277
278 log::debug!("Start address (u32): {}", start_addr);
280
281 match function_code {
282 FunctionCode::ReadU8s => Ok(Request::ReadU8s(address, quantity)),
283 FunctionCode::WriteU8s => {
284 let u8s = cursor.get_ref()[cursor.position() as usize..].to_vec();
285 log::debug!("Parsed U8s: {:?}", u8s);
286
287 Ok(Request::WriteU8s(address, u8s.into()))
291 }
292 FunctionCode::ReadBits => Ok(Request::ReadBits(address, quantity)),
293 FunctionCode::WriteBits => {
294 let bytes = cursor.get_ref()[cursor.position() as usize..].to_vec();
295 let mut bits = bytes_to_bools(&bytes);
296 bits.truncate(quantity as usize);
298 log::debug!("Parsed {} bits: {:?}", quantity, bits);
299 Ok(Request::WriteBits(address, bits.into()))
300 }
301 }
302 }
303}
304
305fn request_command(data: &mut BytesMut, address: u32, code: u8, cnt: u16) {
306 assert!(address <= 0xFFFFFF, "Address out of range for u24");
307 data.put_u16_le((address & 0xFFFF) as u16);
308 data.put_u8((address >> 16) as u8); data.put_u8(code);
310 data.put_u16_le(cnt);
311}
312
313fn parse_address_and_get_instruction_code(address: &str) -> Result<(u32, u8), Error> {
314 let (prefix, number) = split_address(address).unwrap();
315
316 let (code, number_base) = find_instruction_code(prefix).unwrap();
317
318 let u32_number = convert_to_base(number, number_base).unwrap();
319
320 Ok((u32_number, code))
321}
322
323#[cfg(test)]
350mod tests {
351 use super::*;
352 use std::convert::TryFrom;
353
354 #[test]
355 fn test_read_u8s_to_bytes() {
356 let request = Request::ReadU8s("D0".to_owned().into(), 10);
357 let result = Vec::try_from(request);
358 assert!(result.is_ok());
359
360 let bytes = result.unwrap();
361 assert_eq!(bytes.len(), 1);
362
363 let expected_bytes = vec![
364 0x50, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x01, 0x04, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0xA8, 0x0A, 0x00,
366 ];
367
368 assert_eq!(
369 bytes[0].to_vec(),
370 expected_bytes,
371 "The byte block does not match the expected bytes"
372 );
373 }
374
375 #[test]
376 fn test_write_u8s_to_bytes() {
377 let data: Vec<u8> = vec![1, 2, 3, 4];
378 let request = Request::WriteU8s("D0".to_owned().into(), data.clone().into());
379 let result = Vec::try_from(request);
380 assert!(result.is_ok());
381
382 let bytes = result.unwrap();
383 let mut expected_bytes = vec![
384 0x50, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x10, 0x00, 0x10, 0x00, 0x01, 0x14, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0xA8, 0x02, 0x00,
386 ];
387
388 expected_bytes.extend(data);
389
390 assert_eq!(
391 bytes[0].to_vec(),
392 expected_bytes,
393 "The byte block does not match the expected bytes"
394 );
395 }
396
397 #[test]
398 fn test_read_bits_to_bytes() {
399 let request = Request::ReadBits("M0".to_owned().into(), 8);
400 let result = Vec::try_from(request);
401 assert!(result.is_ok());
402
403 let bytes = result.unwrap();
404 assert_eq!(bytes.len(), 1);
405
406 let expected_bytes = vec![
407 0x50, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x01, 0x04, 0x01,
408 0x00, 0x00, 0x00, 0x00, 0x90, 0x08, 0x00,
409 ];
410
411 assert_eq!(
412 bytes[0].to_vec(),
413 expected_bytes,
414 "The ReadBits byte block does not match the expected bytes"
415 );
416 }
417
418 #[test]
419 fn test_read_bits_different_quantities() {
420 let request = Request::ReadBits("M0".to_owned().into(), 1);
422 let result = Vec::try_from(request);
423 assert!(result.is_ok());
424 let bytes = result.unwrap();
425 assert_eq!(bytes.len(), 1);
426
427 let request = Request::ReadBits("M0".to_owned().into(), 16);
429 let result = Vec::try_from(request);
430 assert!(result.is_ok());
431 let bytes = result.unwrap();
432 assert_eq!(bytes.len(), 1);
433
434 let request = Request::ReadBits("M0".to_owned().into(), 2000);
436 let result = Vec::try_from(request);
437 assert!(result.is_ok());
438 let bytes = result.unwrap();
439 assert!(bytes.len() > 1);
441 }
442
443 #[test]
444 fn test_read_bits_different_addresses() {
445 let addresses = vec!["M0", "M100", "M1000", "X0", "Y0"];
447 for addr in addresses {
448 let request = Request::ReadBits(addr.to_owned().into(), 8);
449 let result = Vec::try_from(request);
450 assert!(result.is_ok(), "Failed for address: {}", addr);
451 }
452 }
453
454 #[test]
455 fn test_write_bits_to_bytes() {
456 let data: Vec<bool> = vec![true, false, true, false];
457 let request = Request::WriteBits("M0".to_owned().into(), data.clone().into());
458 let result = Vec::try_from(request);
459 assert!(result.is_ok());
460
461 let bytes = result.unwrap();
462 let mut expected_bytes = vec![
464 0x50, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x0E, 0x00, 0x10, 0x00, 0x01, 0x14, 0x01,
465 0x00, 0x00, 0x00, 0x00, 0x90, 0x04, 0x00,
466 ];
467
468 let len = (data.len() + 1) / 2 + 12;
469
470 expected_bytes[7] = (len & 0xFF) as u8; expected_bytes[8] = ((len >> 8) & 0xFF) as u8; expected_bytes.extend(bools_to_bytes(&data));
476
477 assert_eq!(
479 bytes[0].to_vec(),
480 expected_bytes,
481 "The WriteBits byte block does not match the expected bytes"
482 );
483
484 let odd_data: Vec<bool> = vec![true, false, true];
486 let odd_request = Request::WriteBits("M0".to_owned().into(), odd_data.clone().into());
487 let odd_result = Vec::try_from(odd_request);
488 assert!(odd_result.is_ok());
489 let odd_bytes = odd_result.unwrap();
490 let mut expected_odd_bytes = vec![
491 0x50, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x0E, 0x00, 0x10, 0x00, 0x01, 0x14, 0x01,
492 0x00, 0x00, 0x00, 0x00, 0x90, 0x03, 0x00,
493 ];
494
495 let len = (odd_data.len() + 1) / 2 + 12;
497
498 expected_odd_bytes[7] = (len & 0xFF) as u8; expected_odd_bytes[8] = ((len >> 8) & 0xFF) as u8; expected_odd_bytes.extend(bools_to_bytes(&odd_data));
504
505 assert_eq!(
509 odd_bytes[0].to_vec(),
510 expected_odd_bytes,
511 "The WriteBits byte block for odd length does not match the expected bytes"
512 );
513 }
514
515 #[test]
516 fn test_write_bits_different_patterns() {
517 let data: Vec<bool> = vec![true, true, true, true];
519 let request = Request::WriteBits("M0".to_owned().into(), data.clone().into());
520 let result = Vec::try_from(request);
521 assert!(result.is_ok());
522 let expected_bit_bytes = bools_to_bytes(&data);
523 assert_eq!(expected_bit_bytes, vec![0x11, 0x11]);
524
525 let data: Vec<bool> = vec![false, false, false, false];
527 let request = Request::WriteBits("M0".to_owned().into(), data.clone().into());
528 let result = Vec::try_from(request);
529 assert!(result.is_ok());
530 let expected_bit_bytes = bools_to_bytes(&data);
531 assert_eq!(expected_bit_bytes, vec![0x00, 0x00]);
532
533 let data: Vec<bool> = vec![true, false, true, false, true, false];
535 let request = Request::WriteBits("M0".to_owned().into(), data.clone().into());
536 let result = Vec::try_from(request);
537 assert!(result.is_ok());
538 let expected_bit_bytes = bools_to_bytes(&data);
539 assert_eq!(expected_bit_bytes, vec![0x10, 0x10, 0x10]);
540
541 let data: Vec<bool> = vec![true, false, true];
543 let request = Request::WriteBits("M0".to_owned().into(), data.clone().into());
544 let result = Vec::try_from(request);
545 assert!(result.is_ok());
546 let expected_bit_bytes = bools_to_bytes(&data);
547 assert_eq!(expected_bit_bytes, vec![0x10, 0x10]);
548 }
549
550 #[test]
551 fn test_write_bits_odd_length() {
552 let data: Vec<bool> = vec![true, false, true];
554 let request = Request::WriteBits("M0".to_owned().into(), data.clone().into());
555 let result = Vec::try_from(request);
556 assert!(result.is_ok());
557
558 let expected_bit_bytes = bools_to_bytes(&data);
559 assert_eq!(expected_bit_bytes, vec![0x10, 0x10]);
561 }
562
563 #[test]
564 fn test_write_bits_large_data() {
565 let data: Vec<bool> = (0..2000).map(|i| i % 2 == 0).collect();
567 let request = Request::WriteBits("M0".to_owned().into(), data.clone().into());
568 let result = Vec::try_from(request);
569 assert!(result.is_ok());
570
571 let bytes = result.unwrap();
572 assert!(bytes.len() > 1);
574
575 for byte_chunk in &bytes {
577 assert!(byte_chunk.len() > 21); }
579 }
580
581 #[test]
582 fn test_write_bits_different_addresses() {
583 let data: Vec<bool> = vec![true, false, true, false];
584 let addresses = vec!["M0", "M100", "X0", "Y0"];
585
586 for addr in addresses {
587 let request = Request::WriteBits(addr.to_owned().into(), data.clone().into());
588 let result = Vec::try_from(request);
589 assert!(result.is_ok(), "Failed for address: {}", addr);
590
591 let bytes = result.unwrap();
592 assert_eq!(bytes.len(), 1);
593
594 let byte_vec = bytes[0].to_vec();
596 let bit_data = &byte_vec[21..]; assert_eq!(bit_data, bools_to_bytes(&data));
598 }
599 }
600
601 #[test]
602 fn test_bools_to_bytes() {
603 let bools = vec![true, false, true, false];
604 let bytes = bools_to_bytes(&bools);
605 assert_eq!(bytes, vec![0x10, 0x10]);
606
607 let bools = vec![true, false, true];
608 let bytes = bools_to_bytes(&bools);
609 assert_eq!(bytes, vec![0x10, 0x10]);
610 }
611
612 #[test]
613 fn test_bytes_to_bools() {
614 let bytes = vec![0x10, 0x00];
616 let bools = bytes_to_bools(&bytes);
617 assert_eq!(bools, vec![true, false, false, false]);
618
619 let bytes = vec![0x10, 0x10];
621 let bools = bytes_to_bools(&bytes);
622 assert_eq!(bools, vec![true, false, true, false]);
623 }
624}