Skip to main content

tokio_mc/frame/
mod.rs

1use std::{
2    borrow::Cow,
3    fmt::{self, Display},
4};
5
6pub use types::*;
7
8use crate::bytes::BytesMut;
9
10mod error;
11mod kv;
12mod map;
13mod regex;
14mod types;
15
16pub use error::{map_error_code, ProtocolError};
17
18pub use map::{convert_to_base, find_instruction_code, find_prefix_and_base_by_code};
19pub use regex::split_address;
20
21pub use kv::convert_keyence_to_mitsubishi_address;
22
23pub use kv::KVError;
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum FunctionCode {
27    ReadU8s,
28    WriteU8s,
29    ReadBits,
30    WriteBits,
31}
32
33impl FunctionCode {
34    /// Create a new [`FunctionCode`] with `value`.
35    #[must_use]
36    pub fn new(value: BytesMut) -> Option<Self> {
37        match &value[..] {
38            // MC协议格式: [指令代码(2字节), 子指令代码(2字节)]
39            [0x01, 0x04, 0x00, 0x00] => Some(Self::ReadU8s), // 兼容旧格式
40            [0x01, 0x14, 0x00, 0x00] => Some(Self::WriteU8s), // 兼容旧格式
41            [0x01, 0x04, 0x01, 0x00] => Some(Self::ReadBits), // bit读取
42            [0x01, 0x14, 0x01, 0x00] => Some(Self::WriteBits), // bit写入
43            _ => None,
44        }
45    }
46
47    /// 将 `FunctionCode` 转换为相应的 `BytesMut` 字节序列
48    #[must_use]
49    pub fn value(self) -> BytesMut {
50        let mut buf = BytesMut::new();
51        match self {
52            FunctionCode::ReadU8s => {
53                buf.extend_from_slice(&[0x01, 0x04, 0x00, 0x00]);
54            }
55            FunctionCode::WriteU8s => {
56                buf.extend_from_slice(&[0x01, 0x14, 0x00, 0x00]);
57            }
58            FunctionCode::ReadBits => {
59                buf.extend_from_slice(&[0x01, 0x04, 0x01, 0x00]);
60            }
61            FunctionCode::WriteBits => {
62                buf.extend_from_slice(&[0x01, 0x14, 0x01, 0x00]);
63            }
64        }
65        buf
66    }
67}
68
69impl Display for FunctionCode {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        let bytes = self.value(); // 获取 BytesMut
72        write!(f, "{:?}", &bytes[..]) // 使用 Debug 格式化字节切片
73    }
74}
75
76// 请求的枚举,类似你给出的Modbus请求设计
77#[derive(Debug, Clone, PartialEq)]
78pub enum Request<'a> {
79    ReadU8s(Cow<'a, str>, Quantity),
80    WriteU8s(Cow<'a, str>, Cow<'a, [u8]>),
81    ReadBits(Cow<'a, str>, Quantity),
82    WriteBits(Cow<'a, str>, Cow<'a, [bool]>),
83}
84
85// 实现辅助功能,比如将请求转换为'owned'版本或获取功能码
86impl<'a> Request<'a> {
87    /// 将请求转换为'owned'的实例(静态生命周期)
88    #[must_use]
89    pub fn into_owned(self) -> Request<'static> {
90        use Request::*;
91        match self {
92            ReadU8s(addr, qty) => ReadU8s(Cow::Owned(addr.into_owned()), qty),
93            WriteU8s(addr, u8s) => {
94                WriteU8s(Cow::Owned(addr.into_owned()), Cow::Owned(u8s.into_owned()))
95            }
96            ReadBits(addr, qty) => ReadBits(Cow::Owned(addr.into_owned()), qty),
97            WriteBits(addr, bits) => {
98                WriteBits(Cow::Owned(addr.into_owned()), Cow::Owned(bits.into_owned()))
99            }
100        }
101    }
102
103    #[must_use]
104    pub const fn function_code(&self) -> FunctionCode {
105        use Request::*;
106        match self {
107            ReadU8s(_, _) => FunctionCode::ReadU8s,
108            WriteU8s(_, _) => FunctionCode::WriteU8s,
109            ReadBits(_, _) => FunctionCode::ReadBits,
110            WriteBits(_, _) => FunctionCode::WriteBits,
111        }
112    }
113}
114
115#[derive(Debug, Clone, PartialEq)]
116pub enum Response {
117    ReadU8s(Vec<u8>),
118    WriteU8s(),
119    ReadBits(Vec<bool>),
120    WriteBits(),
121}
122
123pub struct ResponseIterator {
124    response: Response,
125}
126
127impl ResponseIterator {
128    pub fn new(response: Response) -> Self {
129        ResponseIterator { response }
130    }
131}
132
133impl Iterator for ResponseIterator {
134    type Item = Box<dyn std::fmt::Debug>;
135
136    fn next(&mut self) -> Option<Self::Item> {
137        match &mut self.response {
138            Response::ReadU8s(data) => data
139                .pop()
140                .map(|val| Box::new(val) as Box<dyn std::fmt::Debug>),
141            Response::ReadBits(data) => data
142                .pop()
143                .map(|val| Box::new(val) as Box<dyn std::fmt::Debug>),
144            _ => None,
145        }
146    }
147}
148
149impl Response {
150    #[must_use]
151    pub const fn function_code(&self) -> FunctionCode {
152        use Response::*;
153
154        match self {
155            ReadU8s(_) => FunctionCode::ReadU8s,
156            WriteU8s() => FunctionCode::WriteU8s,
157            ReadBits(_) => FunctionCode::ReadBits,
158            WriteBits() => FunctionCode::WriteBits,
159        }
160    }
161
162    // 获取长度
163    pub fn len(&self) -> usize {
164        match self {
165            Response::ReadU8s(values) => values.len() / 2,
166            Response::WriteU8s() => 0,
167            Response::ReadBits(values) => values.len(),
168            Response::WriteBits() => 0,
169        }
170    }
171}
172
173#[cfg(test)]
174mod tests {
175    use super::*;
176
177    #[test]
178    fn new_function_code() {
179        // 测试旧格式兼容性
180        assert_eq!(
181            FunctionCode::ReadU8s,
182            FunctionCode::new(BytesMut::from(&[0x01, 0x04, 0x00, 0x00][..]))
183                .expect("Failed to create FunctionCode from legacy bytes")
184        );
185        assert_eq!(
186            FunctionCode::WriteU8s,
187            FunctionCode::new(BytesMut::from(&[0x01, 0x14, 0x00, 0x00][..]))
188                .expect("Failed to create FunctionCode from legacy bytes")
189        );
190
191        // 测试bit操作
192        assert_eq!(
193            FunctionCode::ReadBits,
194            FunctionCode::new(BytesMut::from(&[0x01, 0x04, 0x01, 0x00][..]))
195                .expect("Failed to create FunctionCode for ReadBits")
196        );
197        assert_eq!(
198            FunctionCode::WriteBits,
199            FunctionCode::new(BytesMut::from(&[0x01, 0x14, 0x01, 0x00][..]))
200                .expect("Failed to create FunctionCode for WriteBits")
201        );
202    }
203
204    #[test]
205    fn function_code_values() {
206        let read_u8s_bytes = BytesMut::from(&[0x01, 0x04, 0x00, 0x00][..]);
207        let write_u8s_bytes = BytesMut::from(&[0x01, 0x14, 0x00, 0x00][..]);
208        let read_bits_bytes = BytesMut::from(&[0x01, 0x04, 0x01, 0x00][..]);
209        let write_bits_bytes = BytesMut::from(&[0x01, 0x14, 0x01, 0x00][..]);
210
211        assert_eq!(
212            FunctionCode::ReadU8s.value(),
213            read_u8s_bytes,
214            "ReadU8s byte sequence is incorrect"
215        );
216
217        assert_eq!(
218            FunctionCode::WriteU8s.value(),
219            write_u8s_bytes,
220            "WriteU8s byte sequence is incorrect"
221        );
222
223        assert_eq!(
224            FunctionCode::ReadBits.value(),
225            read_bits_bytes,
226            "ReadBits byte sequence is incorrect"
227        );
228
229        assert_eq!(
230            FunctionCode::WriteBits.value(),
231            write_bits_bytes,
232            "WriteBits byte sequence is incorrect"
233        );
234    }
235}