modbus_mapping/
codec.rs

1use std::fmt::Debug;
2
3pub use tokio_modbus::{Address, Quantity};
4
5/// 16-bit value stored in Modbus register.
6pub type Word = u16;
7
8#[derive(Debug)]
9pub struct WordsCountError {}
10
11/// Decode a value from Big or Little Endian-ordered `Word`s.
12pub trait Decode: Sized {
13    fn from_be_words(words: &[Word]) -> Result<Self, WordsCountError>;
14    fn from_le_words(words: &[Word]) -> Result<Self, WordsCountError>;
15}
16
17macro_rules! impl_decode {
18    ($num_type:ty) => {
19        impl Decode for $num_type {
20            fn from_be_words(words: &[Word]) -> Result<Self, WordsCountError> {
21                let bytes = words
22                    .iter()
23                    .copied()
24                    .flat_map(u16::to_be_bytes)
25                    .collect::<Vec<u8>>();
26                let array = bytes.try_into().or(Err(WordsCountError {}))?;
27                Ok(<$num_type>::from_be_bytes(array))
28            }
29            fn from_le_words(_words: &[Word]) -> Result<Self, WordsCountError> {
30                todo!()
31            }
32        }
33    };
34}
35
36impl_decode!(i16);
37impl_decode!(i32);
38impl_decode!(i64);
39impl_decode!(u16);
40impl_decode!(u32);
41impl_decode!(u64);
42impl_decode!(f32);
43impl_decode!(f64);
44
45/// Encode a value into Big or Little Endian-ordered `Word`s.
46pub trait Encode {
47    fn to_be_words(self) -> Vec<Word>;
48    fn to_le_words(self) -> Vec<Word>;
49}
50
51macro_rules! impl_encode {
52    ($num_type:ty) => {
53        impl Encode for $num_type {
54            fn to_be_words(self) -> Vec<Word> {
55                self.to_be_bytes()
56                    .chunks(2)
57                    .map(|chunk| {
58                        let array = chunk.try_into().expect("unexpected encoding error");
59                        u16::from_be_bytes(array)
60                    })
61                    .collect()
62            }
63            fn to_le_words(self) -> Vec<Word> {
64                todo!()
65            }
66        }
67    };
68}
69
70impl_encode!(i16);
71impl_encode!(i32);
72impl_encode!(i64);
73impl_encode!(u16);
74impl_encode!(u32);
75impl_encode!(u64);
76impl_encode!(f32);
77impl_encode!(f64);