solis_models/
types.rs

1// The ideia for the PointType trait and the implementation for decode and encode functions
2// were copied from a different crate, available at:
3// https://github.com/lukaskirner/tokio-sunspec/blob/main/src/point.rs
4
5use crate::utils::*;
6
7pub trait PointType<T> {
8    fn decode(data: Vec<u16>) -> T;
9    fn encode(data: T) -> Vec<u16>;
10}
11
12#[derive(Debug, Clone, Copy)]
13pub struct Point<T: PointType<T>> {
14    pub name: &'static str,
15    pub offset: u16,
16    pub length: u16,
17    pub write_access: bool,
18    pub value: T,
19}
20
21impl PointType<i16> for i16 {
22    fn decode(data: Vec<u16>) -> i16 {
23        data[0] as i16
24    }
25
26    fn encode(data: i16) -> Vec<u16> {
27        vec![data as u16]
28    }
29}
30
31impl PointType<i32> for i32 {
32    fn decode(data: Vec<u16>) -> i32 {
33        let bytes = to_be_bytes(data).try_into().unwrap();
34        i32::from_be_bytes(bytes)
35    }
36
37    fn encode(data: i32) -> Vec<u16> {
38        to_u16_vector(&data.to_be_bytes())
39    }
40}
41
42impl PointType<u16> for u16 {
43    fn decode(data: Vec<u16>) -> u16 {
44        data[0]
45    }
46
47    fn encode(data: u16) -> Vec<u16> {
48        vec![data]
49    }
50}
51
52impl PointType<u32> for u32 {
53    fn decode(data: Vec<u16>) -> u32 {
54        let bytes = to_be_bytes(data).try_into().unwrap();
55        u32::from_be_bytes(bytes)
56    }
57
58    fn encode(data: u32) -> Vec<u16> {
59        to_u16_vector(&data.to_be_bytes())
60    }
61}
62
63impl PointType<String> for String {
64    fn decode(data: Vec<u16>) -> String {
65        let bytes: Vec<u8> = to_be_bytes(data);
66        let fbytes: Vec<u8> = bytes.iter().filter(|b| **b != 0).copied().collect();
67        String::from_utf8(fbytes).unwrap()
68    }
69
70    fn encode(data: String) -> Vec<u16> {
71        return to_u16_vector(data.as_bytes());
72    }
73}
74
75impl PointType<Point<String>> for Point<String> {
76    fn decode(data: Vec<u16>) -> Point<String> {
77        let bytes: Vec<u8> = to_be_bytes(data);
78        let fbytes: Vec<u8> = bytes.iter().filter(|b| **b != 0).copied().collect();
79        let data: Point<String> = Point { name: "", offset: 0, length: 0, write_access: false, value: String::from_utf8(fbytes).unwrap() };
80        data
81    }
82
83    fn encode(data: Point<String>) -> Vec<u16> {
84        let mut regs = String::encode(data.value);
85        for _i in 0..(data.length-(regs.len() as u16)){
86            regs.push(0);
87        }
88        regs
89    }
90}
91
92
93#[derive(Debug, Clone)]
94pub enum SDataTypes {
95    SolisU16(Point<u16>),
96    SolisU32(Point<u32>),
97    SolisI16(Point<i16>),
98    SolisI32(Point<i32>),
99    SolisString(Point<String>)
100}
101
102pub trait SolisTypes {
103    // This new function acts as a constructor
104    fn new_u16 (data: u16) -> Self;
105    fn new_u32 (data: u32) -> Self;
106    fn new_i16 (data: i16) -> Self;
107    fn new_i32 (data: i32) -> Self;
108    fn new_string (data: &str) -> Self;
109}
110
111impl SolisTypes for SDataTypes {
112    fn new_u16 (data: u16) -> SDataTypes {
113        SDataTypes::SolisU16(Point { name: "", offset: 0, length: 0, write_access: false, value: data } )
114    }
115    fn new_u32 (data: u32) -> SDataTypes {
116        SDataTypes::SolisU32(Point { name: "", offset: 0, length: 0, write_access: false, value: data } )
117    }
118    fn new_i16 (data: i16) -> SDataTypes {
119        SDataTypes::SolisI16(Point { name: "", offset: 0, length: 0, write_access: false, value: data } )
120    }
121    fn new_i32 (data: i32) -> SDataTypes {
122        SDataTypes::SolisI32(Point { name: "", offset: 0, length: 0, write_access: false, value: data } )
123    }
124    fn new_string (data: &str) -> SDataTypes {
125        SDataTypes::SolisString(Point { name: "", offset: 0, length: 0, write_access: false, value: String::from(data) } )
126    }
127}