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 #[must_use]
36 pub fn new(value: BytesMut) -> Option<Self> {
37 match &value[..] {
38 [0x01, 0x04, 0x00, 0x00] => Some(Self::ReadU8s), [0x01, 0x14, 0x00, 0x00] => Some(Self::WriteU8s), [0x01, 0x04, 0x01, 0x00] => Some(Self::ReadBits), [0x01, 0x14, 0x01, 0x00] => Some(Self::WriteBits), _ => None,
44 }
45 }
46
47 #[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(); write!(f, "{:?}", &bytes[..]) }
74}
75
76#[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
85impl<'a> Request<'a> {
87 #[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 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 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 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}