1
use crate::Word;
2

            
3
use super::{CommandWord, DataWord, StatusWord};
4

            
5
/// Container enum for the different kinds of words
6
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7
pub enum WordType {
8
    /// No contained word
9
    None,
10

            
11
    /// Command word
12
    Command(CommandWord),
13

            
14
    /// Status word
15
    Status(StatusWord),
16

            
17
    /// Data word
18
    Data(DataWord),
19
}
20

            
21
impl WordType {
22
    /// Check if contained word is command
23
    #[must_use = "Returned value is not used"]
24
2
    pub fn is_command(&self) -> bool {
25
2
        matches!(self, Self::Command(_))
26
2
    }
27

            
28
    /// Check if contained word is status
29
    #[must_use = "Returned value is not used"]
30
2
    pub fn is_status(&self) -> bool {
31
2
        matches!(self, Self::Status(_))
32
2
    }
33

            
34
    /// Check if contained word is data
35
    #[must_use = "Returned value is not used"]
36
668
    pub fn is_data(&self) -> bool {
37
668
        matches!(self, Self::Data(_))
38
668
    }
39

            
40
    /// Check if there is a contained word
41
    #[must_use = "Returned value is not used"]
42
528
    pub fn is_some(&self) -> bool {
43
528
        !self.is_none()
44
528
    }
45

            
46
    /// Check if there is no contained word
47
    #[must_use = "Returned value is not used"]
48
1014
    pub fn is_none(&self) -> bool {
49
1014
        matches!(self, Self::None)
50
1014
    }
51

            
52
    /// Get the word as a byte array
53
40
    pub fn bytes(&self) -> [u8; 2] {
54
40
        match self {
55
10
            Self::Command(w) => w.into(),
56
8
            Self::Status(w) => w.into(),
57
20
            Self::Data(w) => w.into(),
58
2
            _ => [0, 0],
59
        }
60
40
    }
61

            
62
    /// Get the parity bit of the word
63
40
    pub fn parity(&self) -> u8 {
64
40
        match self {
65
10
            Self::Command(w) => w.parity(),
66
8
            Self::Status(w) => w.parity(),
67
20
            Self::Data(w) => w.parity(),
68
2
            _ => 0,
69
        }
70
40
    }
71

            
72
    /// Check the parity of the word
73
164
    pub fn check_parity(&self) -> bool {
74
164
        match self {
75
52
            Self::Command(w) => w.check_parity(),
76
20
            Self::Status(w) => w.check_parity(),
77
90
            Self::Data(w) => w.check_parity(),
78
2
            _ => false,
79
        }
80
164
    }
81
}
82

            
83
impl<T> From<T> for WordType
84
where
85
    T: Into<DataWord>,
86
{
87
148
    fn from(value: T) -> Self {
88
148
        WordType::Data(value.into())
89
148
    }
90
}
91

            
92
impl From<CommandWord> for WordType {
93
84
    fn from(value: CommandWord) -> Self {
94
84
        WordType::Command(value)
95
84
    }
96
}
97

            
98
impl From<StatusWord> for WordType {
99
40
    fn from(value: StatusWord) -> Self {
100
40
        WordType::Status(value)
101
40
    }
102
}
103

            
104
#[cfg(test)]
105
mod tests {
106
    use super::*;
107

            
108
    #[test]
109
2
    fn test_wordtype_clone_equal_command() {
110
2
        let item1 = WordType::Command(0b1010101010101010.into());
111
2
        let item2 = item1.clone();
112
2
        assert!(item1 == item2);
113
2
    }
114

            
115
    #[test]
116
2
    fn test_wordtype_clone_equal_status() {
117
2
        let item1 = WordType::Status(0b1010101010101010.into());
118
2
        let item2 = item1.clone();
119
2
        assert!(item1 == item2);
120
2
    }
121

            
122
    #[test]
123
2
    fn test_wordtype_clone_equal_data() {
124
2
        let item1 = WordType::Data(0b1010101010101010.into());
125
2
        let item2 = item1.clone();
126
2
        assert!(item1 == item2);
127
2
    }
128

            
129
    #[test]
130
2
    fn test_wordtype_equal_command() {
131
2
        let item1 = WordType::Command(0b1010101010101010.into());
132
2
        let item2 = WordType::Command(0b1010101010101010.into());
133
2
        assert!(item1 == item2);
134
2
    }
135

            
136
    #[test]
137
2
    fn test_wordtype_not_equal_command() {
138
2
        let item1 = WordType::Command(0b0000000000000000.into());
139
2
        let item2 = WordType::Command(0b1010101010101010.into());
140
2
        assert!(item1 != item2);
141
2
    }
142

            
143
    #[test]
144
2
    fn test_wordtype_equal_status() {
145
2
        let item1 = WordType::Status(0b1010101010101010.into());
146
2
        let item2 = WordType::Status(0b1010101010101010.into());
147
2
        assert!(item1 == item2);
148
2
    }
149

            
150
    #[test]
151
2
    fn test_wordtype_not_equal_status() {
152
2
        let item1 = WordType::Status(0b0000000000000000.into());
153
2
        let item2 = WordType::Status(0b1010101010101010.into());
154
2
        assert!(item1 != item2);
155
2
    }
156

            
157
    #[test]
158
2
    fn test_wordtype_equal_data() {
159
2
        let item1 = WordType::Data(0b1010101010101010.into());
160
2
        let item2 = WordType::Data(0b1010101010101010.into());
161
2
        assert!(item1 == item2);
162
2
    }
163

            
164
    #[test]
165
2
    fn test_wordtype_not_equal_data() {
166
2
        let item1 = WordType::Data(0b0000000000000000.into());
167
2
        let item2 = WordType::Data(0b1010101010101010.into());
168
2
        assert!(item1 != item2);
169
2
    }
170

            
171
    #[test]
172
2
    fn test_wordtype_is_command() {
173
2
        let item = WordType::from(CommandWord::new());
174
2
        assert!(item.is_command());
175
2
    }
176

            
177
    #[test]
178
2
    fn test_wordtype_is_status() {
179
2
        let item = WordType::from(StatusWord::new());
180
2
        assert!(item.is_status());
181
2
    }
182

            
183
    #[test]
184
2
    fn test_wordtype_is_data() {
185
2
        let item = WordType::from(DataWord::new());
186
2
        assert!(item.is_data());
187
2
    }
188

            
189
    #[test]
190
2
    fn test_wordtype_is_some_command() {
191
2
        let item = WordType::from(CommandWord::new());
192
2
        assert!(item.is_some());
193
2
        assert!(!item.is_none());
194
2
    }
195

            
196
    #[test]
197
2
    fn test_wordtype_is_some_status() {
198
2
        let item = WordType::from(StatusWord::new());
199
2
        assert!(item.is_some());
200
2
        assert!(!item.is_none());
201
2
    }
202

            
203
    #[test]
204
2
    fn test_wordtype_is_some_data() {
205
2
        let item = WordType::from(DataWord::new());
206
2
        assert!(item.is_some());
207
2
        assert!(!item.is_none());
208
2
    }
209

            
210
    #[test]
211
2
    fn test_wordtype_is_none() {
212
2
        let item = WordType::None;
213
2
        assert!(!item.is_some());
214
2
        assert!(item.is_none());
215
2
    }
216

            
217
    #[test]
218
2
    fn test_wordtype_bytes_command() {
219
2
        let item = WordType::Command(0b1010101010101010.into());
220
2
        assert_eq!(item.bytes(), [0b10101010, 0b10101010]);
221
2
    }
222

            
223
    #[test]
224
2
    fn test_wordtype_bytes_status() {
225
2
        let item = WordType::Status(0b1010101010101010.into());
226
2
        assert_eq!(item.bytes(), [0b10101010, 0b10101010]);
227
2
    }
228

            
229
    #[test]
230
2
    fn test_wordtype_bytes_data() {
231
2
        let item = WordType::Data(0b1010101010101010.into());
232
2
        assert_eq!(item.bytes(), [0b10101010, 0b10101010]);
233
2
    }
234

            
235
    #[test]
236
2
    fn test_wordtype_bytes_none() {
237
2
        let item = WordType::None;
238
2
        assert_eq!(item.bytes(), [0, 0]);
239
2
    }
240

            
241
    #[test]
242
2
    fn test_wordtype_parity_command() {
243
2
        let item = WordType::from(CommandWord::new().with_parity(1));
244
2
        assert_eq!(item.parity(), 1);
245
2
    }
246

            
247
    #[test]
248
2
    fn test_wordtype_parity_status() {
249
2
        let item = WordType::from(StatusWord::new().with_parity(1));
250
2
        assert_eq!(item.parity(), 1);
251
2
    }
252

            
253
    #[test]
254
2
    fn test_wordtype_parity_data() {
255
2
        let item = WordType::from(DataWord::new().with_parity(1));
256
2
        assert_eq!(item.parity(), 1);
257
2
    }
258

            
259
    #[test]
260
2
    fn test_wordtype_parity_none() {
261
2
        let item = WordType::None;
262
2
        assert_eq!(item.parity(), 0);
263
2
    }
264

            
265
    #[test]
266
2
    fn test_wordtype_check_parity_command() {
267
2
        let item = WordType::from(CommandWord::new().with_parity(1));
268
2
        assert_eq!(item.check_parity(), true);
269
2
    }
270

            
271
    #[test]
272
2
    fn test_wordtype_check_parity_command_fail() {
273
2
        let item = WordType::from(CommandWord::new().with_parity(0));
274
2
        assert_eq!(item.check_parity(), false);
275
2
    }
276

            
277
    #[test]
278
2
    fn test_wordtype_check_parity_status() {
279
2
        let item = WordType::from(StatusWord::new().with_parity(1));
280
2
        assert_eq!(item.check_parity(), true);
281
2
    }
282

            
283
    #[test]
284
2
    fn test_wordtype_check_parity_status_fail() {
285
2
        let item = WordType::from(StatusWord::new().with_parity(0));
286
2
        assert_eq!(item.check_parity(), false);
287
2
    }
288

            
289
    #[test]
290
2
    fn test_wordtype_check_parity_data() {
291
2
        let item = WordType::from(DataWord::new().with_parity(1));
292
2
        assert_eq!(item.check_parity(), true);
293
2
    }
294

            
295
    #[test]
296
2
    fn test_wordtype_check_parity_data_fail() {
297
2
        let item = WordType::from(DataWord::new().with_parity(0));
298
2
        assert_eq!(item.check_parity(), false);
299
2
    }
300

            
301
    #[test]
302
2
    fn test_wordtype_check_parity_none() {
303
2
        assert_eq!(WordType::None.check_parity(), false);
304
2
    }
305
}