1pub fn get_slaveid(data: &[u8]) -> (Option<SlaveId>, Option<&[u8]>) {
10 (
11 data.get(0).map(|byte| SlaveId::new(*byte)),
12 data.get(1..),
13 )
14}
15
16pub unsafe fn get_slaveid_unchecked(data: &[u8]) -> (SlaveId, &[u8]) {
21 (
22 SlaveId::new(*data.get_unchecked(0)),
23 data.get_unchecked(1..),
24 )
25}
26
27#[derive(Debug, Clone, Copy, Hash, Default, PartialEq, Eq, PartialOrd, Ord)]
29pub struct SlaveId(u8);
30
31impl SlaveId {
32 pub const fn new(id: u8) -> Self {
33 Self(id)
34 }
35
36 pub const fn new_default_tcp() -> Self {
42 Self(0xFF)
43 }
44
45 pub const fn new_broadcast() -> Self {
47 Self(0)
48 }
49
50 pub const fn is_device(self) -> bool {
52 !self.is_broadcast() && !self.is_reserved()
53 }
54
55 pub const fn is_reserved(self) -> bool {
57 self.0 >= 248
58 }
59
60 pub const fn is_broadcast(self) -> bool {
62 self.0 == 0
63 }
64
65 pub const fn is_default_tcp(self) -> bool {
67 self.0 == 0xFF
68 }
69
70 pub const fn must_react(self, other: SlaveId) -> bool {
72 if other.0 == 0 {
73 true
74 } else {
75 self.0 == other.0
76 }
77 }
78
79 pub fn from_data(data: &[u8]) -> (Option<Self>, Option<&[u8]>) {
83 get_slaveid(data)
84 }
85
86 pub unsafe fn from_data_unchecked(data: &[u8]) -> (Self, &[u8]) {
91 get_slaveid_unchecked(data)
92 }
93}
94
95impl From<u8> for SlaveId {
96 fn from(sid: u8) -> Self {
97 Self(sid)
98 }
99}
100
101impl Into<u8> for SlaveId {
102 fn into(self) -> u8 {
103 self.0
104 }
105}
106
107#[cfg(test)]
108mod test {
109 use crate::SlaveId;
110
111 #[test]
112 fn new10() {
113 let id = SlaveId::new(10);
114 assert_eq!(id.0, 10);
115 assert!(id.is_device());
116 assert!(!id.is_reserved());
117 assert!(!id.is_default_tcp());
118 assert!(!id.is_broadcast());
119 assert_eq!(id, SlaveId::from(10));
120 }
121
122 #[test]
123 fn device() {
124 assert!(SlaveId::new(20).is_device())
125 }
126
127 #[test]
128 fn broadcast() {
129 assert!(SlaveId::new(0).is_broadcast());
130 assert_eq!(SlaveId::new(0), SlaveId::new_broadcast());
131 assert!(SlaveId::new_broadcast().is_broadcast());
132 }
133
134 #[test]
135 fn tcp() {
136 let tcp = SlaveId::new(0xFF);
137 assert!(tcp.is_default_tcp() && tcp.is_reserved());
138
139 assert_eq!(tcp, SlaveId::new_default_tcp());
140
141 let tcp = SlaveId::new_default_tcp();
142 assert!(tcp.is_default_tcp() && tcp.is_reserved());
143 }
144
145 #[test]
146 fn all_broadcast() {
147 for i in u8::MIN..=u8::MAX {
148 assert!(SlaveId::new(i).must_react(SlaveId::new(0)));
149 assert!(SlaveId::new(i).must_react(SlaveId::new(i)));
150 }
151 }
152
153 #[test]
154 fn all_device() {
155 for i in 1..=247 {
156 assert!(SlaveId::new(i).is_device());
157 assert!(!SlaveId::new(i).is_reserved());
158 assert!(SlaveId::new(i).must_react(SlaveId::new(i)));
159 }
160 }
161
162 #[test]
163 fn all_reserved() {
164 for i in 248..=u8::MAX {
165 assert!(SlaveId::new(i).is_reserved());
166 assert!(!SlaveId::new(i).is_device());
167 assert!(SlaveId::new(i).must_react(SlaveId::new(i)));
168 }
169 }
170}