tokio_mc/codec/
mod.rs

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/// 优化的bool到字节转换,使用预分配和更高效的位操作
19#[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    // 处理成对的bool值
28    for chunk in chunks {
29        result.push((chunk[0] as u8) << 4 | (chunk[1] as u8));
30    }
31
32    // 处理剩余的单个bool值
33    if !remainder.is_empty() {
34        result.push((remainder[0] as u8) << 4);
35    }
36
37    result
38}
39
40/// 优化的字节到bool转换,预分配确切大小
41#[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}
50/// 客户端编码器 - 将 Request 编码为字节数据发送给服务端
51pub struct ClientEncoder;
52
53/// 服务端解码器 - 将客户端发送的字节数据解码为 Request  
54pub struct ServerDecoder;
55
56/// 客户端解码器 - 将服务端返回的字节数据解码为 Response
57pub struct ClientDecoder;
58
59impl ClientEncoder {
60    /// 将 Request 编码为字节数据发送给服务端
61    pub fn encode<'a>(req: Request<'a>) -> Result<Vec<Bytes>, Error> {
62        // 调用现有的 TryFrom 实现
63        Vec::try_from(req)
64    }
65}
66
67impl ServerDecoder {
68    /// 将客户端发送的字节数据解码为 Request
69    pub fn decode(bytes: Bytes) -> Result<Request<'static>, Error> {
70        // 调用现有的 TryFrom 实现
71        Request::try_from(bytes)
72    }
73}
74
75impl ClientDecoder {
76    /// 将服务端返回的字节数据解码为 Response
77    pub fn decode(bytes: Vec<Bytes>, req: Request<'_>) -> Result<Response, Error> {
78        // 调用现有的 TryFrom 实现
79        Response::try_from((bytes, req))
80    }
81}
82
83// 客户端编码: Request -> Vec<Bytes> (客户端发送请求时使用)
84impl<'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                        // bit写入时,每个字节包含实际数据
152                        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
172// 客户端解码: (Vec<Bytes>, Request) -> Response (客户端解析服务端响应时使用)
173impl 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 byte in &bytes {
184        //     check_response(&byte)?;
185        //     data.extend_from_slice(&byte[2..]);
186        // }
187
188        for (i, byte) in bytes.iter().enumerate() {
189            // // 确保至少有 2 字节结束码
190            // if byte.len() < 2 {
191            //     return Err(Error::Protocol(format!("Response too short: {:?}", byte)));
192            // }
193
194            // // 检查结束码是否为 0x0000
195            // let end_code = u16::from_le_bytes([byte[0], byte[1]]);
196            // if end_code != 0x0000 {
197            //     return Err(Error::PlcErrorCode(end_code));
198            // }
199
200            // 提取结束码之后的有效数据(注意:不是 byte[2..] 是跳过 end_code)
201            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
221// impl TryFrom<(Vec<Bytes>)> for Request {
222//     type Error = Error;
223//     fn try_from((bytes): (Vec<Bytes>)) -> Result<Self, Error> {
224//         let mut cursor = Cursor::new(bytes);
225//         let mut instruction_code = [0u8; 4];
226//     }
227// }
228
229// 服务端解码: Bytes -> Request (服务端解析客户端请求时使用)
230impl<'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        // 2. 跳过监视定时器 (2字节)
239        cursor.read_u16::<LittleEndian>()?; // 跳过 [10, 00]
240
241        // 打印cursor的数据
242        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        // 打印prefix
259        log::debug!("Prefix: {}", prefix);
260        // 打印number_base
261        log::debug!("Number base: {:?}", number_base);
262
263        // start_addr根据number_base转换为对应string格式
264        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        // 打印start_addr
279        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                // if u8s.len() != quantity as usize {
288                //     return Err(Error::Protocol(ProtocolError::OutOfRange));
289                // }
290                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                // 根据quantity截取正确数量的位
297                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); // 高位字节
309    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// fn check_response(response_bytes: &[u8]) -> Result<(), Error> {
324//     // let header_len = ResponseHeader::new().len();
325//     // 获取响应字节缓冲区的前 `header_len` 字节,并提取最后两个字节
326//     let last_two_bytes = &response_bytes[..2];
327//     // 将最后两个字节转换为小端格式的 16 位整数
328//     let last_two = LittleEndian::read_u16(last_two_bytes);
329
330//     if let Some(error) = map_error_code(last_two) {
331//         return Err(error.into());
332//     }
333
334//     Ok(())
335// }
336
337// fn reverse(bs: &mut [u8]) {
338//     let len = bs.len();
339//     for i in 0..len / 2 {
340//         let num = i * 2;
341//         let num2 = num + 1;
342
343//         if num2 < len {
344//             bs.swap(num, num2);
345//         }
346//     }
347// }
348
349#[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        // 测试读取1个bit
421        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        // 测试读取16个bit
428        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        // 测试读取大量bit(超过单个请求限制)
435        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        // 应该会分割成多个请求
440        assert!(bytes.len() > 1);
441    }
442
443    #[test]
444    fn test_read_bits_different_addresses() {
445        // 测试不同的地址格式
446        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 bytes = result.unwrap();
463        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_odd_bytes的长度部分
471        expected_bytes[7] = (len & 0xFF) as u8; // 低字节
472        expected_bytes[8] = ((len >> 8) & 0xFF) as u8; // 高字节
473
474        // 添加转换后的bit数据
475        expected_bytes.extend(bools_to_bytes(&data));
476
477        // 计算后续
478        assert_eq!(
479            bytes[0].to_vec(),
480            expected_bytes,
481            "The WriteBits byte block does not match the expected bytes"
482        );
483
484        // 对于奇数长度的bit数组,最后一个bit应该补0
485        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        // 0x0E, 0x00的部分是指令长度
496        let len = (odd_data.len() + 1) / 2 + 12;
497
498        // 替换expected_odd_bytes的长度部分
499        expected_odd_bytes[7] = (len & 0xFF) as u8; // 低字节
500        expected_odd_bytes[8] = ((len >> 8) & 0xFF) as u8; // 高字节
501
502        // 添加转换后的bit数据
503        expected_odd_bytes.extend(bools_to_bytes(&odd_data));
504
505        // println!("Expected odd bytes: {:02X?}", expected_odd_bytes);
506
507        // 计算后续
508        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        // 测试全部为true的bit模式
518        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        // 测试全部为false的bit模式
526        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        // 测试交替模式
534        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        // 为奇数长度的bit数组测试
542        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        // 测试奇数长度的bit数组
553        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        // 奇数长度应该是 [0x10, 0x10] (最后一个bit补0)
560        assert_eq!(expected_bit_bytes, vec![0x10, 0x10]);
561    }
562
563    #[test]
564    fn test_write_bits_large_data() {
565        // 测试大量bit数据(会被分割成多个请求)
566        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        // 应该会分割成多个请求
573        assert!(bytes.len() > 1);
574
575        // 验证每个请求都包含正确的bit数据
576        for byte_chunk in &bytes {
577            assert!(byte_chunk.len() > 21); // 至少包含header + bit数据
578        }
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            // 验证包含的bit数据是正确的
595            let byte_vec = bytes[0].to_vec();
596            let bit_data = &byte_vec[21..]; // bit数据从第21字节开始
597            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        // 测试 [0x10, 0x00] -> [true, false, false, false]
615        let bytes = vec![0x10, 0x00];
616        let bools = bytes_to_bools(&bytes);
617        assert_eq!(bools, vec![true, false, false, false]);
618
619        // 测试 [0x10, 0x10] -> [true, false, true, false]
620        let bytes = vec![0x10, 0x10];
621        let bools = bytes_to_bools(&bytes);
622        assert_eq!(bools, vec![true, false, true, false]);
623    }
624}