1#[macro_use]
2extern crate num_derive;
3
4use std::{convert::TryFrom, fmt, num::TryFromIntError};
5
6mod value;
7
8pub use self::value::*;
9
10#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
12pub struct SlavePos(u16);
13
14impl SlavePos {
15 pub const fn new(p: u16) -> Self {
16 Self(p)
17 }
18}
19
20impl From<u16> for SlavePos {
21 fn from(pos: u16) -> Self {
22 Self(pos)
23 }
24}
25
26impl From<SlavePos> for u16 {
27 fn from(pos: SlavePos) -> Self {
28 pos.0
29 }
30}
31
32impl From<SlavePos> for usize {
33 fn from(pos: SlavePos) -> Self {
34 u16::from(pos) as usize
35 }
36}
37
38#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
40pub struct Idx(u16);
41
42impl Idx {
43 pub const fn new(i: u16) -> Self {
44 Self(i)
45 }
46}
47
48impl From<u16> for Idx {
49 fn from(idx: u16) -> Self {
50 Self(idx)
51 }
52}
53
54impl From<Idx> for u16 {
55 fn from(idx: Idx) -> Self {
56 idx.0
57 }
58}
59
60impl fmt::Debug for Idx {
61 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62 write!(f, "Idx(0x{:04X})", self.0)
63 }
64}
65
66#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
68pub struct SubIdx(u8);
69
70impl SubIdx {
71 pub const fn new(i: u8) -> Self {
72 Self(i)
73 }
74}
75
76impl From<u8> for SubIdx {
77 fn from(sub: u8) -> Self {
78 Self(sub)
79 }
80}
81
82impl From<SubIdx> for u8 {
83 fn from(sub: SubIdx) -> Self {
84 sub.0
85 }
86}
87
88#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
90pub struct SdoPos(u16);
91
92impl SdoPos {
93 pub const fn new(p: u16) -> Self {
94 Self(p)
95 }
96}
97
98impl From<u16> for SdoPos {
99 fn from(pos: u16) -> Self {
100 Self(pos)
101 }
102}
103
104impl From<SdoPos> for u16 {
105 fn from(pos: SdoPos) -> Self {
106 pos.0
107 }
108}
109
110#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
112pub struct PdoPos(u8);
113
114impl PdoPos {
115 pub const fn new(p: u8) -> Self {
116 Self(p)
117 }
118}
119
120impl From<u8> for PdoPos {
121 fn from(pos: u8) -> Self {
122 Self(pos)
123 }
124}
125
126impl From<PdoPos> for u8 {
127 fn from(pos: PdoPos) -> Self {
128 pos.0
129 }
130}
131
132#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
134pub struct PdoEntryPos(u8);
135
136impl PdoEntryPos {
137 pub const fn new(p: u8) -> Self {
138 Self(p)
139 }
140}
141
142impl From<u8> for PdoEntryPos {
143 fn from(pos: u8) -> Self {
144 Self(pos)
145 }
146}
147
148impl From<PdoEntryPos> for u8 {
149 fn from(pos: PdoEntryPos) -> Self {
150 pos.0
151 }
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
156pub struct SdoIdx {
157 pub idx: Idx,
158 pub sub_idx: SubIdx,
159}
160
161impl SdoIdx {
162 pub const fn new(idx: u16, sub: u8) -> Self {
163 Self {
164 idx: Idx::new(idx),
165 sub_idx: SubIdx::new(sub),
166 }
167 }
168}
169
170#[derive(Debug, Clone, PartialEq)]
172pub struct SdoInfo {
173 pub pos: SdoPos, pub idx: Idx,
175 pub max_sub_idx: SubIdx,
176 pub object_code: Option<u8>,
177 pub name: String,
178}
179
180#[derive(Debug, Clone, PartialEq)]
182pub struct SdoEntryInfo {
183 pub data_type: DataType,
184 pub bit_len: u16,
185 pub access: SdoEntryAccess,
186 pub description: String,
187}
188
189#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
191pub enum SdoEntryAddr {
192 ByPos(SdoPos, SubIdx),
193 ByIdx(SdoIdx),
194}
195
196#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
198pub struct SdoEntryAccess {
199 pub pre_op: Access,
200 pub safe_op: Access,
201 pub op: Access,
202}
203
204#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
206pub struct PdoIdx(u16);
207
208impl PdoIdx {
209 pub const fn new(idx: u16) -> Self {
210 Self(idx)
211 }
212}
213
214impl From<u16> for PdoIdx {
215 fn from(idx: u16) -> Self {
216 Self(idx)
217 }
218}
219
220#[derive(Debug, Clone, PartialEq)]
222pub struct PdoInfo {
223 pub sm: SmIdx,
224 pub pos: PdoPos,
225 pub idx: Idx,
226 pub entry_count: u8,
227 pub name: String,
228}
229
230#[derive(Debug, Clone, PartialEq)]
232pub struct PdoEntryInfo {
233 pub pos: PdoEntryPos,
234 pub entry_idx: PdoEntryIdx,
235 pub bit_len: u8,
236 pub name: String,
237}
238
239impl From<PdoIdx> for u16 {
240 fn from(idx: PdoIdx) -> Self {
241 idx.0
242 }
243}
244
245#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
247pub struct PdoEntryIdx {
248 pub idx: Idx,
249 pub sub_idx: SubIdx,
250}
251
252impl PdoEntryIdx {
253 pub const fn new(idx: u16, sub: u8) -> Self {
254 Self {
255 idx: Idx::new(idx),
256 sub_idx: SubIdx::new(sub),
257 }
258 }
259}
260
261#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
263pub struct DomainIdx(usize);
264
265impl DomainIdx {
266 pub const fn new(idx: usize) -> Self {
267 Self(idx)
268 }
269}
270
271impl From<usize> for DomainIdx {
272 fn from(idx: usize) -> Self {
273 Self(idx)
274 }
275}
276
277impl From<DomainIdx> for usize {
278 fn from(idx: DomainIdx) -> Self {
279 idx.0
280 }
281}
282
283impl TryFrom<DomainIdx> for u32 {
284 type Error = TryFromIntError;
285 fn try_from(idx: DomainIdx) -> Result<Self, Self::Error> {
286 u32::try_from(idx.0)
287 }
288}
289
290impl TryFrom<DomainIdx> for u64 {
291 type Error = TryFromIntError;
292 fn try_from(idx: DomainIdx) -> Result<Self, Self::Error> {
293 u64::try_from(idx.0)
294 }
295}
296
297#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
299pub struct SmIdx(u8);
300
301impl SmIdx {
302 pub const fn new(idx: u8) -> Self {
303 Self(idx)
304 }
305}
306
307impl From<u8> for SmIdx {
308 fn from(idx: u8) -> Self {
309 Self(idx)
310 }
311}
312
313impl From<SmIdx> for u8 {
314 fn from(idx: SmIdx) -> Self {
315 idx.0
316 }
317}
318
319#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
321pub enum Access {
322 ReadOnly,
324 ReadWrite,
326 WriteOnly,
328 Unknown,
330}
331
332#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, FromPrimitive)]
334pub enum DataType {
335 Bool = 0x001,
337 Byte = 0x01E,
339
340 I8 = 0x0002,
342 I16 = 0x0003,
344 I32 = 0x0004,
346 I64 = 0x0015,
348
349 U8 = 0x0005,
351 U16 = 0x0006,
353 U32 = 0x0007,
355 U64 = 0x001B,
357
358 F32 = 0x0008,
360 F64 = 0x0011,
362
363 String = 0x0009,
365
366 U8Array = 0x000A,
368
369 U16Array = 0x000B,
371
372 I24 = 0x0010,
373 I40 = 0x0012,
374 I48 = 0x0013,
375 I56 = 0x0014,
376
377 U24 = 0x0016,
378 U40 = 0x0018,
379 U48 = 0x0019,
380 U56 = 0x001A,
381
382 Bit1 = 0x0030,
384 Bit2 = 0x0031,
386 Bit3 = 0x0032,
388 Bit4 = 0x0033,
390 Bit5 = 0x0034,
392 Bit6 = 0x0035,
394 Bit7 = 0x0036,
396 Bit8 = 0x0037,
398
399 TimeOfDay = 0x000C,
401 TimeDifference = 0x000D,
403
404 Domain = 0x000F,
406
407 Raw = 0xFFFF,
408}
409
410#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
412pub struct Offset {
413 pub byte: usize,
414 pub bit: u32,
415}
416
417#[derive(Debug, Clone, Copy, PartialEq)]
419pub enum AlState {
420 Boot = 0x3,
421 Init = 0x1,
422 PreOp = 0x2,
423 SafeOp = 0x4,
424 Op = 0x8,
425}
426
427#[derive(Debug)]
428pub struct InvalidAlStateError;
429
430impl TryFrom<u8> for AlState {
431 type Error = InvalidAlStateError;
432 fn try_from(st: u8) -> Result<Self, Self::Error> {
433 match st {
434 1 => Ok(AlState::Init),
435 2 => Ok(AlState::PreOp),
436 3 => Ok(AlState::Boot),
437 4 => Ok(AlState::SafeOp),
438 8 => Ok(AlState::Op),
439 _ => Err(InvalidAlStateError),
440 }
441 }
442}
443
444impl From<AlState> for u8 {
445 fn from(st: AlState) -> Self {
446 st as u8
447 }
448}
449
450#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
452pub enum SmType {
453 Unused = 0,
455 MbxWr = 1,
457 MbxRd = 2,
459 Outputs = 3,
461 Inputs = 4,
463}
464
465#[derive(Debug)]
466pub struct InvalidSmTypeError;
467
468impl TryFrom<u8> for SmType {
469 type Error = InvalidSmTypeError;
470 fn try_from(st: u8) -> Result<Self, Self::Error> {
471 match st {
472 0 => Ok(SmType::Unused),
473 1 => Ok(SmType::MbxWr),
474 2 => Ok(SmType::MbxRd),
475 3 => Ok(SmType::Outputs),
476 4 => Ok(SmType::Inputs),
477 _ => Err(InvalidSmTypeError),
478 }
479 }
480}
481
482impl From<SmType> for u8 {
483 fn from(st: SmType) -> Self {
484 st as u8
485 }
486}
487
488#[cfg(test)]
489mod tests {
490 use super::*;
491
492 #[test]
493 fn u8_from_al_state() {
494 assert_eq!(u8::from(AlState::Init), 1);
495 assert_eq!(u8::from(AlState::PreOp), 2);
496 assert_eq!(u8::from(AlState::Boot), 3);
497 assert_eq!(u8::from(AlState::SafeOp), 4);
498 assert_eq!(u8::from(AlState::Op), 8);
499 }
500
501 #[test]
502 fn try_al_state_from_u8() {
503 assert_eq!(AlState::try_from(1).unwrap(), AlState::Init);
504 assert_eq!(AlState::try_from(2).unwrap(), AlState::PreOp);
505 assert_eq!(AlState::try_from(3).unwrap(), AlState::Boot);
506 assert_eq!(AlState::try_from(4).unwrap(), AlState::SafeOp);
507 assert_eq!(AlState::try_from(8).unwrap(), AlState::Op);
508 assert!(AlState::try_from(0).is_err());
509 assert!(AlState::try_from(5).is_err());
510 assert!(AlState::try_from(6).is_err());
511 assert!(AlState::try_from(7).is_err());
512 }
513
514 #[test]
515 fn try_sm_type_from_u8() {
516 assert_eq!(SmType::try_from(0).unwrap(), SmType::Unused);
517 assert_eq!(SmType::try_from(1).unwrap(), SmType::MbxWr);
518 assert_eq!(SmType::try_from(2).unwrap(), SmType::MbxRd);
519 assert_eq!(SmType::try_from(3).unwrap(), SmType::Outputs);
520 assert_eq!(SmType::try_from(4).unwrap(), SmType::Inputs);
521 assert!(AlState::try_from(5).is_err());
522 }
523
524 #[test]
525 fn u8_from_sm_type() {
526 assert_eq!(u8::from(SmType::Unused), 0);
527 assert_eq!(u8::from(SmType::MbxWr), 1);
528 assert_eq!(u8::from(SmType::MbxRd), 2);
529 assert_eq!(u8::from(SmType::Outputs), 3);
530 assert_eq!(u8::from(SmType::Inputs), 4);
531 }
532
533 #[test]
534 fn debug_idx() {
535 assert_eq!(format!("{:?}", Idx::new(0)), "Idx(0x0000)");
536 assert_eq!(format!("{:?}", Idx::new(u16::MAX)), "Idx(0xFFFF)");
537 }
538}