1
//! Error enums and flags
2

            
3
/// A result type which uses the [Error] enum as the error type.
4
pub type Result<T> = core::result::Result<T, Error>;
5

            
6
/// Calculate a parity bit given a u16 word value
7
///
8
/// MIL STD 1553B uses an odd parity bit (1 if the
9
/// bit count of the data is even, 0 if not)[^1].
10
///
11
/// [^1]: [MIL-STD-1553 Tutorial](http://www.horntech.cn/techDocuments/MIL-STD-1553Tutorial.pdf)
12
#[inline]
13
#[must_use = "Returned value is not used"]
14
956
pub(crate) const fn parity(v: u16) -> u8 {
15
956
    match v.count_ones() % 2 {
16
454
        0 => 1,
17
502
        _ => 0,
18
    }
19
956
}
20

            
21
/// An error deriving from the software itself, rather than a terminal.
22
///
23
/// These errors occur during parsing or other calculations when those
24
/// calculations fail. The [Error::SystemError] variant
25
/// contains any errors generated by the 1553 bus.
26
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
27
#[repr(u8)]
28
pub enum Error {
29
    /// An index or range was out of bounds
30
    OutOfBounds,
31

            
32
    /// A packet was found to be invalid
33
    InvalidPacket,
34

            
35
    /// A word was found to be invalid
36
    InvalidWord,
37

            
38
    /// The given string is the wrong size or encoding
39
    InvalidString,
40

            
41
    /// The message is full and cannot accept words
42
    MessageFull,
43

            
44
    /// A message cannot begin with a data word
45
    DataFirst,
46

            
47
    /// Cannot add header words after the first word
48
    HeaderNotFirst,
49

            
50
    /// The message is invalid
51
    InvalidMessage,
52

            
53
    /// An error from a terminal (see [SystemError])
54
    SystemError(SystemError),
55
}
56

            
57
/// An error deriving from a remote terminal or bus controller.
58
///
59
/// These errors are generated during runtime by terminals and
60
/// provided in messages on the bus.
61
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
62
#[repr(u8)]
63
pub enum SystemError {
64
    /// No error
65
    None,
66

            
67
    /// A terminal error (see [TerminalError] for more information)
68
    Terminal(TerminalError),
69

            
70
    /// A subsystem error (see [SubsystemError] for more information)
71
    Subsystem(SubsystemError),
72

            
73
    /// A message error (see [MessageError] for more information)
74
    Message(MessageError),
75
}
76

            
77
/// This flag is to inform the bus controller of faults in a remote terminal
78
///
79
/// The error bit flag defined here maps to the Terminal Flag bit at bit
80
/// time 19 (index 15). It is used to notify the bus controller of a fault
81
/// or failure within the *entire* remote terminal, rather than only the
82
/// channel on which the error was received.
83
///
84
/// This flag is described on page 35 in the MIL-STD-1553 Tutorial[^1].
85
///
86
/// [^1]: [MIL-STD-1553 Tutorial](http://www.horntech.cn/techDocuments/MIL-STD-1553Tutorial.pdf)
87
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
88
#[repr(u8)]
89
pub enum TerminalError {
90
    /// No error
91
    None = 0,
92

            
93
    /// An error has occurred
94
    Error = 1,
95
}
96

            
97
impl TerminalError {
98
    /// Check if the enum is the 'None' variant
99
    #[must_use = "Returned value is not used"]
100
6
    pub const fn is_none(&self) -> bool {
101
6
        matches!(self, Self::None)
102
6
    }
103

            
104
    /// Check if the enum is the 'Error' variant
105
    #[must_use = "Returned value is not used"]
106
14
    pub const fn is_error(&self) -> bool {
107
14
        matches!(self, Self::Error)
108
14
    }
109
}
110

            
111
impl From<u8> for TerminalError {
112
20
    fn from(value: u8) -> Self {
113
20
        match value {
114
8
            1 => Self::Error,
115
12
            _ => Self::None,
116
        }
117
20
    }
118
}
119

            
120
impl From<TerminalError> for u8 {
121
14
    fn from(value: TerminalError) -> Self {
122
14
        match value {
123
8
            TerminalError::Error => 1,
124
6
            TerminalError::None => 0,
125
        }
126
14
    }
127
}
128

            
129
impl From<u16> for TerminalError {
130
16
    fn from(value: u16) -> Self {
131
16
        Self::from(value as u8)
132
16
    }
133
}
134

            
135
impl From<TerminalError> for u16 {
136
4
    fn from(value: TerminalError) -> Self {
137
4
        u8::from(value) as u16
138
4
    }
139
}
140

            
141
/// This flag provides health data regarding subsystems of a remote terminal.
142
///
143
/// The Subsystem Flag bit located at bit time 17 (index 13) is used to provide
144
/// “health” data regarding the subsystems to which the remote terminal is connected.
145
///
146
/// Multiple subsystems may logically OR their bits together to form a composite
147
/// health indicator. This indicator only informs the bus controller that a fault
148
/// or failure exists, and further information must be obtained in some other fashion.
149
///
150
/// This flag is described on page 34 in the MIL-STD-1553 Tutorial[^1].
151
///
152
/// [^1]: [MIL-STD-1553 Tutorial](http://www.horntech.cn/techDocuments/MIL-STD-1553Tutorial.pdf)
153
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
154
#[repr(u8)]
155
pub enum SubsystemError {
156
    /// No error
157
    None = 0,
158

            
159
    /// An error has occurred
160
    Error = 1,
161
}
162

            
163
impl SubsystemError {
164
    /// Check if the enum is 'None' variant
165
    #[must_use = "Returned value is not used"]
166
6
    pub const fn is_none(&self) -> bool {
167
6
        matches!(self, Self::None)
168
6
    }
169

            
170
    /// Check if the enum is 'Error' variant
171
    #[must_use = "Returned value is not used"]
172
16
    pub const fn is_error(&self) -> bool {
173
16
        matches!(self, Self::Error)
174
16
    }
175
}
176

            
177
impl From<u8> for SubsystemError {
178
22
    fn from(value: u8) -> Self {
179
22
        match value {
180
8
            1 => Self::Error,
181
14
            _ => Self::None,
182
        }
183
22
    }
184
}
185

            
186
impl From<SubsystemError> for u8 {
187
14
    fn from(value: SubsystemError) -> Self {
188
14
        match value {
189
8
            SubsystemError::Error => 1,
190
6
            SubsystemError::None => 0,
191
        }
192
14
    }
193
}
194

            
195
impl From<u16> for SubsystemError {
196
18
    fn from(value: u16) -> Self {
197
18
        Self::from(value as u8)
198
18
    }
199
}
200

            
201
impl From<SubsystemError> for u16 {
202
4
    fn from(value: SubsystemError) -> Self {
203
4
        u8::from(value) as u16
204
4
    }
205
}
206

            
207
/// This flag is set when a receiving terminal detects an error in a message.
208
///
209
/// The error may have occurred in any of the data words within the message, and
210
/// when a terminal receives this flag in a message, it will ignore all data
211
/// words in the containing message. If an error is detected within a message
212
/// and this flag is set, the remote terminal must suppress transmission of the
213
/// status word. If an illegal command is detected, this flag is set and the
214
/// status word is transmitted.
215
///
216
/// This flag is described on page 32 in the MIL-STD-1553 Tutorial[^1].
217
///
218
/// [^1]: [MIL-STD-1553 Tutorial](http://www.horntech.cn/techDocuments/MIL-STD-1553Tutorial.pdf)
219
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
220
#[repr(u8)]
221
pub enum MessageError {
222
    /// No error
223
    None = 0,
224

            
225
    /// An error has occurred
226
    Error = 1,
227
}
228

            
229
impl MessageError {
230
    /// Check if the enum is 'None' variant
231
    #[must_use = "Returned value is not used"]
232
6
    pub const fn is_none(&self) -> bool {
233
6
        matches!(self, Self::None)
234
6
    }
235

            
236
    /// Check if enum is 'Error' variant
237
    #[must_use = "Returned value is not used"]
238
18
    pub const fn is_error(&self) -> bool {
239
18
        matches!(self, Self::Error)
240
18
    }
241
}
242

            
243
impl From<u8> for MessageError {
244
24
    fn from(value: u8) -> Self {
245
24
        match value {
246
8
            1 => Self::Error,
247
16
            _ => Self::None,
248
        }
249
24
    }
250
}
251

            
252
impl From<MessageError> for u8 {
253
14
    fn from(value: MessageError) -> Self {
254
14
        match value {
255
8
            MessageError::Error => 1,
256
6
            MessageError::None => 0,
257
        }
258
14
    }
259
}
260

            
261
impl From<u16> for MessageError {
262
20
    fn from(value: u16) -> Self {
263
20
        Self::from(value as u8)
264
20
    }
265
}
266

            
267
impl From<MessageError> for u16 {
268
4
    fn from(value: MessageError) -> Self {
269
4
        u8::from(value) as u16
270
4
    }
271
}
272

            
273
#[cfg(test)]
274
mod tests {
275
    use super::*;
276

            
277
    #[test]
278
2
    fn test_parity_0() {
279
2
        let value = parity(0b1010101010101010);
280
2
        assert_eq!(value, 1);
281
2
    }
282

            
283
    #[test]
284
2
    fn test_parity_1() {
285
2
        let value = parity(0b1010101010101000);
286
2
        assert_eq!(value, 0);
287
2
    }
288

            
289
    #[test]
290
2
    fn test_parity_2() {
291
2
        let value = parity(0b1010101010100000);
292
2
        assert_eq!(value, 1);
293
2
    }
294

            
295
    #[test]
296
2
    fn test_parity_3() {
297
2
        let value = parity(0b1010101010000000);
298
2
        assert_eq!(value, 0);
299
2
    }
300

            
301
    #[test]
302
2
    fn test_system_error_clone() {
303
2
        let error1 = SystemError::Terminal(TerminalError::Error);
304
2
        let error2 = error1.clone();
305
2
        assert_eq!(error1, error2);
306
2
    }
307

            
308
    #[test]
309
2
    fn test_terminal_error_clone() {
310
2
        let error1 = TerminalError::Error;
311
2
        let error2 = error1.clone();
312
2
        assert_eq!(error1, error2);
313
2
    }
314

            
315
    #[test]
316
2
    fn test_terminal_error() {
317
2
        let error = TerminalError::None;
318
2
        assert!(error.is_none());
319

            
320
2
        let error = TerminalError::Error;
321
2
        assert!(error.is_error());
322
2
    }
323

            
324
    #[test]
325
2
    fn test_terminal_error_from_u8() {
326
2
        let error = TerminalError::from(0u8);
327
2
        assert!(error.is_none());
328

            
329
2
        let error = TerminalError::from(1u8);
330
2
        assert!(error.is_error());
331
2
    }
332

            
333
    #[test]
334
2
    fn test_u8_from_terminal_error() {
335
2
        let error = u8::from(TerminalError::None);
336
2
        assert_eq!(error, 0);
337

            
338
2
        let error = u8::from(TerminalError::Error);
339
2
        assert_eq!(error, 1);
340
2
    }
341

            
342
    #[test]
343
2
    fn test_terminal_error_from_u16() {
344
2
        let error = TerminalError::from(0u16);
345
2
        assert!(error.is_none());
346

            
347
2
        let error = TerminalError::from(1u16);
348
2
        assert!(error.is_error());
349
2
    }
350

            
351
    #[test]
352
2
    fn test_u16_from_terminal_error() {
353
2
        let error = u16::from(TerminalError::None);
354
2
        assert_eq!(error, 0);
355

            
356
2
        let error = u16::from(TerminalError::Error);
357
2
        assert_eq!(error, 1);
358
2
    }
359

            
360
    #[test]
361
2
    fn test_subsystem_error_clone() {
362
2
        let error1 = SubsystemError::Error;
363
2
        let error2 = error1.clone();
364
2
        assert_eq!(error1, error2);
365
2
    }
366

            
367
    #[test]
368
2
    fn test_subsystem_error() {
369
2
        let error = SubsystemError::None;
370
2
        assert!(error.is_none());
371

            
372
2
        let error = SubsystemError::Error;
373
2
        assert!(error.is_error());
374
2
    }
375

            
376
    #[test]
377
2
    fn test_subsystem_error_from_u8() {
378
2
        let error = SubsystemError::from(0u8);
379
2
        assert!(error.is_none());
380

            
381
2
        let error = SubsystemError::from(1u8);
382
2
        assert!(error.is_error());
383
2
    }
384

            
385
    #[test]
386
2
    fn test_u8_from_subsystem_error() {
387
2
        let error = u8::from(SubsystemError::None);
388
2
        assert_eq!(error, 0);
389

            
390
2
        let error = u8::from(SubsystemError::Error);
391
2
        assert_eq!(error, 1);
392
2
    }
393

            
394
    #[test]
395
2
    fn test_subsystem_error_from_u16() {
396
2
        let error = SubsystemError::from(0u16);
397
2
        assert!(error.is_none());
398

            
399
2
        let error = SubsystemError::from(1u16);
400
2
        assert!(error.is_error());
401
2
    }
402

            
403
    #[test]
404
2
    fn test_u16_from_subsystem_error() {
405
2
        let error = u16::from(SubsystemError::None);
406
2
        assert_eq!(error, 0);
407

            
408
2
        let error = u16::from(SubsystemError::Error);
409
2
        assert_eq!(error, 1);
410
2
    }
411

            
412
    #[test]
413
2
    fn test_message_error_clone() {
414
2
        let error1 = MessageError::Error;
415
2
        let error2 = error1.clone();
416
2
        assert_eq!(error1, error2);
417
2
    }
418

            
419
    #[test]
420
2
    fn test_message_error() {
421
2
        let error = MessageError::None;
422
2
        assert!(error.is_none());
423

            
424
2
        let error = MessageError::Error;
425
2
        assert!(error.is_error());
426
2
    }
427

            
428
    #[test]
429
2
    fn test_message_error_from_u8() {
430
2
        let error = MessageError::from(0u8);
431
2
        assert!(error.is_none());
432

            
433
2
        let error = MessageError::from(1u8);
434
2
        assert!(error.is_error());
435
2
    }
436

            
437
    #[test]
438
2
    fn test_u8_from_message_error() {
439
2
        let error = u8::from(MessageError::None);
440
2
        assert_eq!(error, 0);
441

            
442
2
        let error = u8::from(MessageError::Error);
443
2
        assert_eq!(error, 1);
444
2
    }
445

            
446
    #[test]
447
2
    fn test_message_error_from_u16() {
448
2
        let error = MessageError::from(0u16);
449
2
        assert!(error.is_none());
450

            
451
2
        let error = MessageError::from(1u16);
452
2
        assert!(error.is_error());
453
2
    }
454

            
455
    #[test]
456
2
    fn test_u16_from_message_error() {
457
2
        let error = u16::from(MessageError::None);
458
2
        assert_eq!(error, 0);
459

            
460
2
        let error = u16::from(MessageError::Error);
461
2
        assert_eq!(error, 1);
462
2
    }
463
}