1
use crate::errors::{parity, Error, MessageError, Result, SubsystemError, TerminalError};
2
use crate::fields::*;
3
use crate::{flags::*, Header, Word};
4

            
5
/// Specifies the function that a remote terminal is to perform
6
///
7
/// This word is parsed from a packet that includes an initial service
8
/// sync flag. Only the active bus controller emits this word.[^1]
9
///
10
/// ## Example
11
///
12
/// ```rust
13
/// # use mil_std_1553b::*;
14
/// # fn main() -> Result<()> {
15
///     let word = CommandWord::new()
16
///         .with_address(Address::Value(16))
17
///         .with_subaddress(SubAddress::ModeCode(0))
18
///         .with_transmit_receive(TransmitReceive::Receive)
19
///         .with_mode_code(ModeCode::TransmitterShutdown)
20
///         .with_calculated_parity()
21
///         .build()?;
22
///
23
///     assert_eq!(word.subaddress(),SubAddress::ModeCode(0));
24
///     assert_eq!(word.mode_code(),ModeCode::TransmitterShutdown);
25
/// # Ok(())
26
/// # }
27
/// ```
28
///
29
/// [^1]: p30 [MIL-STD-1553 Tutorial](http://www.horntech.cn/techDocuments/MIL-STD-1553Tutorial.pdf)
30
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31
pub struct CommandWord {
32
    /// Data of the word
33
    data: [u8; 2],
34

            
35
    /// Parity of the word
36
    parity: u8,
37
}
38

            
39
/// Sent in response to a valid message from the bus controller
40
///
41
/// This word is parsed from a packet that includes an initial service
42
/// sync flag. Status words are only transmitted by a remote terminal
43
/// in response to a message from the bus controller.[^1]
44
///
45
/// ## Example
46
///
47
/// ```rust
48
/// # use mil_std_1553b::*;
49
/// # fn main() -> Result<()> {
50
///     let word = StatusWord::new()
51
///         .with_address(Address::Value(16))
52
///         .with_service_request(ServiceRequest::Service)
53
///         .with_broadcast_received(BroadcastReceived::Received)
54
///         .with_calculated_parity()
55
///         .build()?;
56
///
57
///     assert_eq!(word.broadcast_received(),BroadcastReceived::Received);
58
///     assert_eq!(word.service_request(),ServiceRequest::Service);
59
/// # Ok(())
60
/// # }
61
/// ```
62
///
63
/// [^1]: p31 [MIL-STD-1553 Tutorial](http://www.horntech.cn/techDocuments/MIL-STD-1553Tutorial.pdf)
64
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65
pub struct StatusWord {
66
    /// Data of the word
67
    data: [u8; 2],
68

            
69
    /// Parity of the word
70
    parity: u8,
71
}
72

            
73
/// Contains data that is being transmitted in a message.
74
///
75
/// This word is parsed from a packet that includes an initial data
76
/// sync flag. Data words can be transmitted by either a remote terminal
77
/// (transmit command) or a bus controller (receive command) and contain
78
/// two bytes of data each.[^1]
79
///
80
/// ## Example
81
///
82
/// ```rust
83
/// # use mil_std_1553b::*;
84
/// # fn main() -> Result<()> {
85
///     let word = DataWord::new()
86
///         .with_value(0b0100100001001001u16)
87
///         .with_calculated_parity()
88
///         .build()?;
89
///
90
///     assert_eq!(word.as_string(),Ok("HI"));
91
/// # Ok(())
92
/// # }
93
/// ```
94
///
95
/// [^1]: p31 [MIL-STD-1553 Tutorial](http://www.horntech.cn/techDocuments/MIL-STD-1553Tutorial.pdf)
96
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97
pub struct DataWord {
98
    /// Data of the word
99
    data: [u8; 2],
100

            
101
    /// Parity of the word
102
    parity: u8,
103
}
104

            
105
impl CommandWord {
106
    /// Get the terminal address of this word
107
    ///
108
    /// See [Address](crate::flags::Address) for more information
109
    /// about this field.
110
4
    pub fn address(&self) -> Address {
111
4
        COMMAND_ADDRESS_FIELD.get(self)
112
4
    }
113

            
114
    /// Set the terminal address of this word
115
    ///
116
    /// See [CommandWord::address] for
117
    /// more information.
118
    ///
119
    /// # Arguments
120
    ///
121
    /// * `value` - An [Address] to set
122
    ///
123
4
    pub fn set_address(&mut self, value: Address) {
124
4
        COMMAND_ADDRESS_FIELD.set(self, value.into());
125
4
    }
126

            
127
    /// Constructor method to set the terminal address
128
    ///
129
    /// See [CommandWord::address] for
130
    /// more information.
131
    ///
132
    /// # Arguments
133
    ///
134
    /// * `value` - An [Address] to set
135
    ///
136
2
    pub fn with_address(mut self, value: Address) -> Self {
137
2
        self.set_address(value);
138
2
        self
139
2
    }
140

            
141
    /// Get the subaddress of this word
142
    ///
143
    /// Values of 0b00000 and 0b11111 are interpreted as a flag that
144
    /// indicates that this command is carrying a mode code value.
145
    ///
146
    /// See [SubAddress](crate::flags::SubAddress) for more information
147
    /// about this field.
148
10
    pub fn subaddress(&self) -> SubAddress {
149
10
        COMMAND_SUBADDRESS_FIELD.get(self)
150
10
    }
151

            
152
    /// Set the subaddress of this word
153
    ///
154
    /// See [CommandWord::subaddress] for
155
    /// more information.
156
    ///
157
    /// # Arguments
158
    ///
159
    /// * `value` - A [SubAddress] to set
160
    ///
161
10
    pub fn set_subaddress(&mut self, value: SubAddress) {
162
10
        COMMAND_SUBADDRESS_FIELD.set(self, value.into());
163
10
    }
164

            
165
    /// Constructor method to set the subaddress
166
    ///
167
    /// See [CommandWord::subaddress] for
168
    /// more information.
169
    ///
170
    /// # Arguments
171
    ///
172
    /// * `value` - A [SubAddress] to set
173
    ///
174
2
    pub fn with_subaddress(mut self, value: SubAddress) -> Self {
175
2
        self.set_subaddress(value);
176
2
        self
177
2
    }
178

            
179
    /// Get the direction of transmission
180
    ///
181
    /// See [TransmitReceive](crate::flags::TransmitReceive) enum for
182
    /// more information about this field.
183
12
    pub fn transmit_receive(&self) -> TransmitReceive {
184
12
        COMMAND_TRANSMIT_RECEIVE_FIELD.get(self)
185
12
    }
186

            
187
    /// Set the direction of transmission
188
    ///
189
    /// See [TransmitReceive](crate::flags::TransmitReceive) enum for
190
    /// more information about this field.
191
    ///
192
    /// # Arguments
193
    ///
194
    /// * `value` - A [TransmitReceive] flag to set
195
    ///
196
12
    pub fn set_transmit_receive(&mut self, value: TransmitReceive) {
197
12
        COMMAND_TRANSMIT_RECEIVE_FIELD.set(self, value.into());
198
12
    }
199

            
200
    /// Constructor method to set the direction of transmission
201
    ///
202
    /// See [TransmitReceive](crate::flags::TransmitReceive) enum for
203
    /// more information about this field.
204
    ///
205
    /// # Arguments
206
    ///
207
    /// * `value` - A [TransmitReceive] flag to set
208
    ///
209
2
    pub fn with_transmit_receive(mut self, value: TransmitReceive) -> Self {
210
2
        self.set_transmit_receive(value);
211
2
        self
212
2
    }
213

            
214
    /// Get the mode code of this word
215
    ///
216
    /// This field should not be used if the subaddress isn't set to
217
    /// a ModeCode value. See [ModeCode](crate::flags::ModeCode) for
218
    /// more information about this field, or [SubAddress](crate::flags::SubAddress)
219
    /// for details about the ModeCode setting of the subaddress.
220
4
    pub fn mode_code(&self) -> ModeCode {
221
4
        COMMAND_MODE_CODE_FIELD.get(self)
222
4
    }
223

            
224
    /// Set the mode code of this word
225
    ///
226
    /// This method sets the same bits that are used by the word count field.
227
    /// In order to be valid, users must also set the subaddress to a valid
228
    /// mode code value. See [CommandWord::mode_code] for more information.
229
    ///
230
    /// # Arguments
231
    ///
232
    /// * `value` - A [ModeCode] flag to set
233
    ///
234
4
    pub fn set_mode_code(&mut self, value: ModeCode) {
235
4
        COMMAND_MODE_CODE_FIELD.set(self, value.into());
236
4
    }
237

            
238
    /// Constructor method to set the mode code
239
    ///
240
    /// This method sets the same bits that are used by the word count field.
241
    /// In order to be valid, users must also set the subaddress to a valid
242
    /// mode code value. See [CommandWord::mode_code] for more information.
243
    ///
244
    /// # Arguments
245
    ///
246
    /// * `value` - A [ModeCode] flag to set
247
    ///
248
2
    pub fn with_mode_code(mut self, value: ModeCode) -> Self {
249
2
        self.set_mode_code(value);
250
2
        self
251
2
    }
252

            
253
    /// Get the number of data words associated with this word
254
    ///
255
    /// The word count is a value between 0 and 32 in command words
256
    /// that are not mode code commands. Mode code commands are
257
    /// identified using particular values of the subaddress field.
258
    ///
259
    /// See [SubAddress](crate::flags::SubAddress) for details about
260
    /// the ModeCode setting of the subaddress.
261
86
    pub fn word_count(&self) -> u8 {
262
86
        match COMMAND_WORD_COUNT_FIELD.get(self) {
263
6
            0 => 32u8,
264
80
            k => k as u8,
265
        }
266
86
    }
267

            
268
    /// Set the number of data words associated with this command
269
    ///
270
    /// The word count field is stored in the same bit position as the
271
    /// mode code value, and should only be used if the sub address is
272
    /// *not* set to a ModeCode value. See [CommandWord::word_count]
273
    /// for more information.
274
    ///
275
    /// Commands that are not mode code require some number of data
276
    /// words, and setting this field to `0` will indicate 32 data
277
    /// words. Any value given greater than 31 will be converted to
278
    /// `0`.
279
    ///
280
    /// # Arguments
281
    ///
282
    /// * `value` - A word count to set
283
    ///
284
12
    pub fn set_word_count(&mut self, mut value: u8) {
285
12
        if value > 31 {
286
6
            value = 0;
287
6
        }
288
12
        COMMAND_WORD_COUNT_FIELD.set(self, value);
289
12
    }
290

            
291
    /// Constructor method to set the number of data words
292
    ///
293
    /// See [CommandWord::set_word_count] for more information.
294
    ///
295
    /// # Arguments
296
    ///
297
    /// * `value` - A word count to set
298
    ///
299
6
    pub fn with_word_count(mut self, value: u8) -> Self {
300
6
        self.set_word_count(value);
301
6
        self
302
6
    }
303

            
304
    /// Check if this word contains a mode code value
305
    ///
306
    /// See [CommandWord::mode_code]
307
    /// for more information.
308
    #[must_use = "Returned value is not used"]
309
6
    pub fn is_mode_code(&self) -> bool {
310
6
        self.subaddress().is_mode_code()
311
6
    }
312

            
313
    /// Check if this word is being transmitted to a terminal
314
    ///
315
    /// See [CommandWord::transmit_receive]
316
    /// for more information.
317
    #[must_use = "Returned value is not used"]
318
4
    pub fn is_transmit(&self) -> bool {
319
4
        self.transmit_receive().is_transmit()
320
4
    }
321

            
322
    /// Check if this word is being received by a terminal
323
    ///
324
    /// See [CommandWord::transmit_receive]
325
    /// for more information.
326
    #[must_use = "Returned value is not used"]
327
4
    pub fn is_receive(&self) -> bool {
328
4
        self.transmit_receive().is_receive()
329
4
    }
330

            
331
    /// Get the data word count of the command word
332
    #[must_use = "Returned value is not used"]
333
72
    pub fn count(&self) -> usize {
334
72
        self.word_count() as usize
335
72
    }
336
}
337

            
338
impl StatusWord {
339
    /// Get the terminal address of this word
340
    ///
341
    /// See [Address](crate::flags::Address) for more information
342
    /// about this field.
343
4
    pub fn address(&self) -> Address {
344
4
        STATUS_ADDRESS_FIELD.get(self)
345
4
    }
346

            
347
    /// Set the terminal address of this word
348
    ///
349
    /// See [StatusWord::address] for
350
    /// more information.
351
    ///
352
    /// # Arguments
353
    ///
354
    /// * `value` - An [Address] to set
355
    ///
356
4
    pub fn set_address(&mut self, value: Address) {
357
4
        STATUS_ADDRESS_FIELD.set(self, value.into());
358
4
    }
359

            
360
    /// Constructor method to set the terminal address
361
    ///
362
    /// See [StatusWord::address] for
363
    /// more information.
364
    ///
365
    /// # Arguments
366
    ///
367
    /// * `value` - An [Address] to set
368
    ///
369
2
    pub fn with_address(mut self, value: Address) -> Self {
370
2
        self.set_address(value);
371
2
        self
372
2
    }
373

            
374
    /// Get Instrumentation flag of the status word
375
    ///
376
    /// **Most systems no longer use this flag, as the cost in reduced subaddress
377
    /// range is too high**.
378
    ///
379
    /// See [Instrumentation](crate::flags::Instrumentation) for
380
    /// more information.
381
4
    pub fn instrumentation(&self) -> Instrumentation {
382
4
        STATUS_INSTRUMENTATION_FIELD.get(self)
383
4
    }
384

            
385
    /// Set Instrumentation flag of the status word
386
    ///
387
    /// See [StatusWord::instrumentation] for
388
    /// more information.
389
    ///
390
    /// # Arguments
391
    ///
392
    /// * `value` - An [Instrumentation] flag to set
393
    ///
394
4
    pub fn set_instrumentation(&mut self, value: Instrumentation) {
395
4
        STATUS_INSTRUMENTATION_FIELD.set(self, value.into());
396
4
    }
397

            
398
    /// Constructor method to set Instrumentation flag
399
    ///
400
    /// See [StatusWord::instrumentation] for
401
    /// more information.
402
    ///
403
    /// # Arguments
404
    ///
405
    /// * `value` - An [Instrumentation] flag to set
406
    ///
407
2
    pub fn with_instrumentation(mut self, value: Instrumentation) -> Self {
408
2
        self.set_instrumentation(value);
409
2
        self
410
2
    }
411

            
412
    /// Get Service Request flag of the status word
413
    ///
414
    /// See [ServiceRequest](crate::flags::ServiceRequest) for
415
    /// more information.
416
4
    pub fn service_request(&self) -> ServiceRequest {
417
4
        STATUS_SERVICE_REQUEST_FIELD.get(self)
418
4
    }
419

            
420
    /// Set Service Request flag of the status word
421
    ///
422
    /// See [StatusWord::service_request] for
423
    /// more information.
424
    ///
425
    /// # Arguments
426
    ///
427
    /// * `value` - A [ServiceRequest] flag to set
428
    ///
429
4
    pub fn set_service_request(&mut self, value: ServiceRequest) {
430
4
        STATUS_SERVICE_REQUEST_FIELD.set(self, value.into());
431
4
    }
432

            
433
    /// Constructor method to set the Service Request flag
434
    ///
435
    /// See [StatusWord::service_request] for
436
    /// more information.
437
    ///
438
    /// # Arguments
439
    ///
440
    /// * `value` - A [ServiceRequest] flag to set
441
    ///
442
2
    pub fn with_service_request(mut self, value: ServiceRequest) -> Self {
443
2
        self.set_service_request(value);
444
2
        self
445
2
    }
446

            
447
    /// Get the value of the reserved portion of the status word
448
    ///
449
    /// See [Reserved](crate::flags::Reserved) for
450
    /// more information.
451
4
    pub fn reserved(&self) -> Reserved {
452
4
        STATUS_RESERVED_FIELD.get(self)
453
4
    }
454

            
455
    /// Set the value of the reserved portion of the status word
456
    ///
457
    /// See [StatusWord::reserved] for
458
    /// more information.
459
    ///
460
    /// # Arguments
461
    ///
462
    /// * `value` - A [Reserved] value to set
463
    ///
464
4
    pub fn set_reserved(&mut self, value: Reserved) {
465
4
        STATUS_RESERVED_FIELD.set(self, value.into());
466
4
    }
467

            
468
    /// Constructor method to set the value of the reserved field
469
    ///
470
    /// See [StatusWord::reserved] for
471
    /// more information.
472
    ///
473
    /// # Arguments
474
    ///
475
    /// * `value` - A [Reserved] value to set
476
    ///
477
2
    pub fn with_reserved(mut self, value: Reserved) -> Self {
478
2
        self.set_reserved(value);
479
2
        self
480
2
    }
481

            
482
    /// Get the Broadcast Command flag from the status word
483
    ///
484
    /// If set, the flag indicates that the terminal has received a valid
485
    /// broadcast command. See [BroadcastReceived](crate::flags::BroadcastReceived) for
486
    /// more information.
487
4
    pub fn broadcast_received(&self) -> BroadcastReceived {
488
4
        STATUS_BROADCAST_RECEIVED_FIELD.get(self)
489
4
    }
490

            
491
    /// Set the Broadcast Command flag of the status word
492
    ///
493
    /// See [StatusWord::broadcast_received] for
494
    /// more information.
495
    ///
496
    /// # Arguments
497
    ///
498
    /// * `value` - A [BroadcastReceived] flag to set
499
    ///
500
4
    pub fn set_broadcast_received(&mut self, value: BroadcastReceived) {
501
4
        STATUS_BROADCAST_RECEIVED_FIELD.set(self, value.into());
502
4
    }
503

            
504
    /// Constructor method to set the Broadcast Command flag
505
    ///
506
    /// See [StatusWord::broadcast_received] for
507
    /// more information.
508
    ///
509
    /// # Arguments
510
    ///
511
    /// * `value` - A [BroadcastReceived] flag to set
512
    ///
513
2
    pub fn with_broadcast_received(mut self, value: BroadcastReceived) -> Self {
514
2
        self.set_broadcast_received(value);
515
2
        self
516
2
    }
517

            
518
    /// Get the Busy flag from the status word
519
    ///
520
    /// If set, the flag indicates that the terminal is unable to respond to
521
    /// commands at this time. See [TerminalBusy](crate::flags::TerminalBusy) for
522
    /// more information.
523
8
    pub fn terminal_busy(&self) -> TerminalBusy {
524
8
        STATUS_TERMINAL_BUSY_FIELD.get(self)
525
8
    }
526

            
527
    /// Set the Busy flag on the status word
528
    ///
529
    /// See [StatusWord::terminal_busy] for
530
    /// more information.
531
    ///
532
    /// # Arguments
533
    ///
534
    /// * `value` - A [TerminalBusy] flag to set
535
    ///
536
4
    pub fn set_terminal_busy(&mut self, value: TerminalBusy) {
537
4
        STATUS_TERMINAL_BUSY_FIELD.set(self, value.into());
538
4
    }
539

            
540
    /// Constructor method to set the Busy flag
541
    ///
542
    /// See [StatusWord::terminal_busy] for
543
    /// more information.
544
    ///
545
    /// # Arguments
546
    ///
547
    /// * `value` - A [TerminalBusy] flag to set
548
    ///
549
2
    pub fn with_terminal_busy(mut self, value: TerminalBusy) -> Self {
550
2
        self.set_terminal_busy(value);
551
2
        self
552
2
    }
553

            
554
    /// Get the Dynamic Bus Control Acceptance flag from the status word
555
    ///
556
    /// If set, the flag indicates that the terminal is taking control
557
    /// of the bus. See [DynamicBusAcceptance](crate::flags::DynamicBusAcceptance) for
558
    /// more information.
559
4
    pub fn dynamic_bus_acceptance(&self) -> DynamicBusAcceptance {
560
4
        STATUS_DYNAMIC_BUS_ACCEPTANCE_FIELD.get(self)
561
4
    }
562

            
563
    /// Set the Dynamic Bus Control Acceptance flag on the status word
564
    ///
565
    /// See [StatusWord::dynamic_bus_acceptance] for
566
    /// more information.
567
    ///
568
    /// # Arguments
569
    ///
570
    /// * `value` - A [DynamicBusAcceptance] flag to set
571
    ///
572
4
    pub fn set_dynamic_bus_acceptance(&mut self, value: DynamicBusAcceptance) {
573
4
        STATUS_DYNAMIC_BUS_ACCEPTANCE_FIELD.set(self, value.into());
574
4
    }
575

            
576
    /// Constructor method to set the Dynamic Bus Control Acceptance flag
577
    ///
578
    /// See [StatusWord::dynamic_bus_acceptance] for
579
    /// more information.
580
    ///
581
    /// # Arguments
582
    ///
583
    /// * `value` - A [DynamicBusAcceptance] flag to set
584
    ///
585
2
    pub fn with_dynamic_bus_acceptance(mut self, value: DynamicBusAcceptance) -> Self {
586
2
        self.set_dynamic_bus_acceptance(value);
587
2
        self
588
2
    }
589

            
590
    /// Check if the message error flag is set
591
    ///
592
    /// See [MessageError] for more
593
    /// information.
594
16
    pub fn message_error(&self) -> MessageError {
595
16
        STATUS_MESSAGE_ERROR_FIELD.get(self)
596
16
    }
597

            
598
    /// Set the message error flag on this word
599
    ///
600
    /// See [StatusWord::message_error] for
601
    /// more information.
602
    ///
603
    /// # Arguments
604
    ///
605
    /// * `value` - A [MessageError] flag to set
606
    ///
607
6
    pub fn set_message_error(&mut self, value: MessageError) {
608
6
        STATUS_MESSAGE_ERROR_FIELD.set(self, value.into());
609
6
    }
610

            
611
    /// Constructor method to set the message error flag
612
    ///
613
    /// See [StatusWord::message_error] for
614
    /// more information.
615
    ///
616
    /// # Arguments
617
    ///
618
    /// * `value` - A [MessageError] flag to set
619
    ///
620
2
    pub fn with_message_error(mut self, value: MessageError) -> Self {
621
2
        self.set_message_error(value);
622
2
        self
623
2
    }
624

            
625
    /// Check if the subsystem error flag is set
626
    ///
627
    /// See [SubsystemError](crate::errors::SubsystemError) for more
628
    /// information.
629
14
    pub fn subsystem_error(&self) -> SubsystemError {
630
14
        STATUS_SUBSYSTEM_ERROR_FIELD.get(self)
631
14
    }
632

            
633
    /// Set the subsystem error flag on this word
634
    ///
635
    /// See [StatusWord::subsystem_error] for
636
    /// more information.
637
    ///
638
    /// # Arguments
639
    ///
640
    /// * `value` - A [SubsystemError] flag to set
641
    ///
642
6
    pub fn set_subsystem_error(&mut self, value: SubsystemError) {
643
6
        STATUS_SUBSYSTEM_ERROR_FIELD.set(self, value.into());
644
6
    }
645

            
646
    /// Constructor method to set the subsystem error flag
647
    ///
648
    /// See [StatusWord::subsystem_error] for
649
    /// more information.
650
    ///
651
    /// # Arguments
652
    ///
653
    /// * `value` - A [SubsystemError] flag to set
654
    ///
655
2
    pub fn with_subsystem_error(mut self, value: SubsystemError) -> Self {
656
2
        self.set_subsystem_error(value);
657
2
        self
658
2
    }
659

            
660
    /// Check if the terminal error flag is set
661
    ///
662
    /// See [`TerminalError`](crate::errors::TerminalError) for more
663
    /// information.
664
12
    pub fn terminal_error(&self) -> TerminalError {
665
12
        STATUS_TERMINAL_ERROR_FIELD.get(self)
666
12
    }
667

            
668
    /// Set the terminal error flag on this word
669
    ///
670
    /// See [`StatusWord::terminal_error`][StatusWord::terminal_error] for
671
    /// more information.
672
    ///
673
    /// # Arguments
674
    ///
675
    /// * `value` - A [TerminalError] flag to set
676
    ///
677
6
    pub fn set_terminal_error(&mut self, value: TerminalError) {
678
6
        STATUS_TERMINAL_ERROR_FIELD.set(self, value.into());
679
6
    }
680

            
681
    /// Constructor set the terminal error flag
682
    ///
683
    /// See [`StatusWord::terminal_error`][StatusWord::terminal_error] for
684
    /// more information.
685
    ///
686
    /// # Arguments
687
    ///
688
    /// * `value` - A [TerminalError] flag to set
689
    ///
690
2
    pub fn with_terminal_error(mut self, value: TerminalError) -> Self {
691
2
        self.set_terminal_error(value);
692
2
        self
693
2
    }
694

            
695
    /// Check if any of the various error flags are set
696
    ///
697
    /// See [StatusWord::message_error], [StatusWord::subsystem_error],
698
    /// or [StatusWord::terminal_error] for more information.
699
    #[must_use = "Returned value is not used"]
700
12
    pub fn is_error(&self) -> bool {
701
12
        self.message_error().is_error()
702
10
            || self.subsystem_error().is_error()
703
8
            || self.terminal_error().is_error()
704
12
    }
705

            
706
    /// Check if the terminal is currently busy
707
    ///
708
    /// See [StatusWord::terminal_busy] for
709
    /// more information.
710
    #[must_use = "Returned value is not used"]
711
4
    pub fn is_busy(&self) -> bool {
712
4
        self.terminal_busy().is_busy()
713
4
    }
714
}
715

            
716
impl DataWord {
717
    /// Constructor method to set the word from a string
718
    ///
719
    /// Fails if the given string is more than two
720
    /// bytes long.
721
    ///
722
    /// # Arguments
723
    ///
724
    /// * `data` - A &str to set as data
725
    ///
726
8
    pub fn with_string(mut self, data: &str) -> Result<Self> {
727
8
        self.set_string(data)?;
728
6
        Ok(self)
729
8
    }
730

            
731
    /// Set the word from a string
732
    ///
733
    /// Fails if the given string is more than two
734
    /// bytes long.
735
    ///
736
    /// # Arguments
737
    ///
738
    /// * `data` - A &str to set as data
739
    ///
740
12
    pub fn set_string(&mut self, data: &str) -> Result<()> {
741
12
        self.data = data.as_bytes().try_into().or(Err(Error::InvalidString))?;
742
8
        self.parity = self.calculate_parity();
743
8
        Ok(())
744
12
    }
745

            
746
    /// Get the internal data as a &str
747
    ///
748
    /// Fails if the word is not a valid UTF-8 string.
749
8
    pub fn as_string(&self) -> Result<&str> {
750
8
        self.try_into()
751
8
    }
752
}
753

            
754
impl Header for CommandWord {
755
10
    fn count(&self) -> Option<usize> {
756
10
        Some(self.word_count() as usize)
757
10
    }
758
}
759

            
760
impl Header for StatusWord {
761
8
    fn count(&self) -> Option<usize> {
762
8
        None
763
8
    }
764
}
765

            
766
impl Word for CommandWord {
767
160
    fn new() -> Self {
768
160
        Self {
769
160
            data: [0, 0],
770
160
            parity: 1,
771
160
        }
772
160
    }
773

            
774
100
    fn with_value(mut self, data: u16) -> Self {
775
100
        self.set_value(data);
776
100
        self
777
100
    }
778

            
779
18
    fn with_bytes(mut self, data: [u8; 2]) -> Self {
780
18
        self.set_bytes(data);
781
18
        self
782
18
    }
783

            
784
22
    fn with_parity(mut self, parity: u8) -> Self {
785
22
        self.set_parity(parity);
786
22
        self
787
22
    }
788

            
789
100
    fn with_calculated_parity(mut self) -> Self {
790
100
        self.parity = self.calculate_parity();
791
100
        self
792
100
    }
793

            
794
14
    fn build(self) -> Result<Self> {
795
14
        if self.check_parity() {
796
12
            Ok(self)
797
        } else {
798
2
            Err(Error::InvalidWord)
799
        }
800
14
    }
801

            
802
96
    fn from_value(data: u16) -> Self {
803
96
        Self::new().with_value(data).with_calculated_parity()
804
96
    }
805

            
806
6
    fn from_bytes(data: [u8; 2]) -> Self {
807
6
        Self::new().with_bytes(data)
808
6
    }
809

            
810
10
    fn as_bytes(&self) -> [u8; 2] {
811
10
        self.data
812
10
    }
813

            
814
508
    fn as_value(&self) -> u16 {
815
508
        self.into()
816
508
    }
817

            
818
144
    fn set_value(&mut self, data: u16) {
819
144
        self.data = data.to_be_bytes();
820
144
        self.parity = self.calculate_parity();
821
144
    }
822

            
823
20
    fn set_bytes(&mut self, data: [u8; 2]) {
824
20
        self.data = data;
825
20
        self.parity = self.calculate_parity();
826
20
    }
827

            
828
88
    fn parity(&self) -> u8 {
829
88
        self.parity
830
88
    }
831

            
832
24
    fn set_parity(&mut self, parity: u8) {
833
24
        self.parity = parity;
834
24
    }
835

            
836
336
    fn calculate_parity(&self) -> u8 {
837
336
        parity(self.as_value())
838
336
    }
839

            
840
72
    fn check_parity(&self) -> bool {
841
72
        self.parity() == self.calculate_parity()
842
72
    }
843
}
844

            
845
impl Word for StatusWord {
846
122
    fn new() -> Self {
847
122
        Self {
848
122
            data: [0, 0],
849
122
            parity: 1,
850
122
        }
851
122
    }
852

            
853
54
    fn with_value(mut self, data: u16) -> Self {
854
54
        self.set_value(data);
855
54
        self
856
54
    }
857

            
858
18
    fn with_bytes(mut self, data: [u8; 2]) -> Self {
859
18
        self.set_bytes(data);
860
18
        self
861
18
    }
862

            
863
22
    fn with_parity(mut self, parity: u8) -> Self {
864
22
        self.set_parity(parity);
865
22
        self
866
22
    }
867

            
868
4
    fn with_calculated_parity(mut self) -> Self {
869
4
        self.parity = self.calculate_parity();
870
4
        self
871
4
    }
872

            
873
14
    fn build(self) -> Result<Self> {
874
14
        if self.check_parity() {
875
12
            Ok(self)
876
        } else {
877
2
            Err(Error::InvalidWord)
878
        }
879
14
    }
880

            
881
50
    fn from_value(data: u16) -> Self {
882
50
        Self::new().with_value(data)
883
50
    }
884

            
885
6
    fn from_bytes(data: [u8; 2]) -> Self {
886
6
        Self::new().with_bytes(data)
887
6
    }
888

            
889
10
    fn as_bytes(&self) -> [u8; 2] {
890
10
        self.data
891
10
    }
892

            
893
298
    fn as_value(&self) -> u16 {
894
298
        self.into()
895
298
    }
896

            
897
102
    fn set_value(&mut self, data: u16) {
898
102
        self.data = data.to_be_bytes();
899
102
        self.parity = self.calculate_parity();
900
102
    }
901

            
902
20
    fn set_bytes(&mut self, data: [u8; 2]) {
903
20
        self.data = data;
904
20
        self.parity = self.calculate_parity();
905
20
    }
906

            
907
54
    fn parity(&self) -> u8 {
908
54
        self.parity
909
54
    }
910

            
911
24
    fn set_parity(&mut self, parity: u8) {
912
24
        self.parity = parity;
913
24
    }
914

            
915
166
    fn calculate_parity(&self) -> u8 {
916
166
        parity(self.as_value())
917
166
    }
918

            
919
40
    fn check_parity(&self) -> bool {
920
40
        self.parity() == self.calculate_parity()
921
40
    }
922
}
923

            
924
impl Word for DataWord {
925
258
    fn new() -> Self {
926
258
        Self {
927
258
            data: [0, 0],
928
258
            parity: 1,
929
258
        }
930
258
    }
931

            
932
104
    fn with_value(mut self, data: u16) -> Self {
933
104
        self.set_value(data);
934
104
        self
935
104
    }
936

            
937
128
    fn with_bytes(mut self, data: [u8; 2]) -> Self {
938
128
        self.set_bytes(data);
939
128
        self
940
128
    }
941

            
942
30
    fn with_parity(mut self, parity: u8) -> Self {
943
30
        self.set_parity(parity);
944
30
        self
945
30
    }
946

            
947
6
    fn with_calculated_parity(mut self) -> Self {
948
6
        self.parity = self.calculate_parity();
949
6
        self
950
6
    }
951

            
952
24
    fn build(self) -> Result<Self> {
953
24
        if self.check_parity() {
954
22
            Ok(self)
955
        } else {
956
2
            Err(Error::InvalidWord)
957
        }
958
24
    }
959

            
960
102
    fn from_value(data: u16) -> Self {
961
102
        Self::new().with_value(data)
962
102
    }
963

            
964
106
    fn from_bytes(data: [u8; 2]) -> Self {
965
106
        Self::new().with_bytes(data)
966
106
    }
967

            
968
14
    fn as_bytes(&self) -> [u8; 2] {
969
14
        self.data
970
14
    }
971

            
972
428
    fn as_value(&self) -> u16 {
973
428
        self.into()
974
428
    }
975

            
976
118
    fn set_value(&mut self, data: u16) {
977
118
        self.data = data.to_be_bytes();
978
118
        self.parity = self.calculate_parity();
979
118
    }
980

            
981
130
    fn set_bytes(&mut self, data: [u8; 2]) {
982
130
        self.data = data;
983
130
        self.parity = self.calculate_parity();
984
130
    }
985

            
986
154
    fn parity(&self) -> u8 {
987
154
        self.parity
988
154
    }
989

            
990
32
    fn set_parity(&mut self, parity: u8) {
991
32
        self.parity = parity;
992
32
    }
993

            
994
382
    fn calculate_parity(&self) -> u8 {
995
382
        parity(self.as_value())
996
382
    }
997

            
998
120
    fn check_parity(&self) -> bool {
999
120
        self.parity() == self.calculate_parity()
120
    }
}
impl Default for CommandWord {
2
    fn default() -> Self {
2
        Self::new()
2
    }
}
impl Default for StatusWord {
2
    fn default() -> Self {
2
        Self::new()
2
    }
}
impl Default for DataWord {
2
    fn default() -> Self {
2
        Self::new()
2
    }
}
impl TryFrom<&str> for DataWord {
    type Error = Error;
4
    fn try_from(value: &str) -> Result<Self> {
4
        Self::new()
4
            .with_string(value)
5
            .map(|w| w.with_calculated_parity())
4
    }
}
impl<'a> TryFrom<&'a DataWord> for &'a str {
    type Error = Error;
22
    fn try_from(value: &'a DataWord) -> Result<Self> {
22
        core::str::from_utf8(&value.data).or(Err(Error::InvalidString))
22
    }
}
impl From<u16> for CommandWord {
92
    fn from(value: u16) -> Self {
92
        Self::from_value(value)
92
    }
}
impl From<u16> for StatusWord {
46
    fn from(value: u16) -> Self {
46
        Self::from_value(value)
46
    }
}
impl From<u16> for DataWord {
98
    fn from(value: u16) -> Self {
98
        Self::from_value(value)
98
    }
}
impl From<[u8; 2]> for CommandWord {
2
    fn from(value: [u8; 2]) -> Self {
2
        Self::from_bytes(value)
2
    }
}
impl From<[u8; 2]> for StatusWord {
2
    fn from(value: [u8; 2]) -> Self {
2
        Self::from_bytes(value)
2
    }
}
impl From<[u8; 2]> for DataWord {
102
    fn from(value: [u8; 2]) -> Self {
102
        Self::from_bytes(value)
102
    }
}
impl From<&CommandWord> for [u8; 2] {
10
    fn from(value: &CommandWord) -> Self {
10
        value.data
10
    }
}
impl From<CommandWord> for [u8; 2] {
2
    fn from(value: CommandWord) -> Self {
2
        value.data
2
    }
}
impl From<&StatusWord> for [u8; 2] {
8
    fn from(value: &StatusWord) -> Self {
8
        value.data
8
    }
}
impl From<StatusWord> for [u8; 2] {
2
    fn from(value: StatusWord) -> Self {
2
        value.data
2
    }
}
impl From<&DataWord> for [u8; 2] {
34
    fn from(value: &DataWord) -> Self {
34
        value.data
34
    }
}
impl From<DataWord> for [u8; 2] {
2
    fn from(value: DataWord) -> Self {
2
        value.data
2
    }
}
impl From<&CommandWord> for u16 {
508
    fn from(value: &CommandWord) -> Self {
508
        u16::from_be_bytes(value.data)
508
    }
}
impl From<CommandWord> for u16 {
2
    fn from(value: CommandWord) -> Self {
2
        u16::from_be_bytes(value.data)
2
    }
}
impl From<&StatusWord> for u16 {
298
    fn from(value: &StatusWord) -> Self {
298
        u16::from_be_bytes(value.data)
298
    }
}
impl From<StatusWord> for u16 {
2
    fn from(value: StatusWord) -> Self {
2
        u16::from_be_bytes(value.data)
2
    }
}
impl From<&DataWord> for u16 {
446
    fn from(value: &DataWord) -> Self {
446
        u16::from_be_bytes(value.data)
446
    }
}
impl From<DataWord> for u16 {
2
    fn from(value: DataWord) -> Self {
2
        u16::from(&value)
2
    }
}
impl From<&DataWord> for i16 {
2
    fn from(value: &DataWord) -> Self {
2
        u16::from(value) as i16
2
    }
}
impl From<DataWord> for i16 {
2
    fn from(value: DataWord) -> Self {
2
        i16::from(&value)
2
    }
}
impl From<&DataWord> for u32 {
2
    fn from(value: &DataWord) -> Self {
2
        u16::from(value) as u32
2
    }
}
impl From<DataWord> for u32 {
2
    fn from(value: DataWord) -> Self {
2
        u32::from(&value)
2
    }
}
impl From<&DataWord> for i32 {
2
    fn from(value: &DataWord) -> Self {
2
        u16::from(value) as i32
2
    }
}
impl From<DataWord> for i32 {
2
    fn from(value: DataWord) -> Self {
2
        i32::from(&value)
2
    }
}
impl From<&DataWord> for u64 {
2
    fn from(value: &DataWord) -> Self {
2
        u16::from(value) as u64
2
    }
}
impl From<DataWord> for u64 {
2
    fn from(value: DataWord) -> Self {
2
        u64::from(&value)
2
    }
}
impl From<&DataWord> for i64 {
2
    fn from(value: &DataWord) -> Self {
2
        u16::from(value) as i64
2
    }
}
impl From<DataWord> for i64 {
2
    fn from(value: DataWord) -> Self {
2
        i64::from(&value)
2
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    // ----------------------------------------------------------
    // CommandWord
    #[test]
2
    fn test_command_get_set_address() {
2
        let value1 = Address::Broadcast(0b11111);
2
        let value2 = Address::Value(0b10101);
2

            
2
        let mut word = CommandWord::new().with_address(value1);
2
        assert_eq!(word.address(), value1);
2
        word.set_address(value2);
2
        assert_eq!(word.address(), value2);
2
        assert_eq!(word.as_value(), 0b1010100000000000);
2
    }
    #[test]
2
    fn test_command_get_set_subaddress() {
2
        let value1 = SubAddress::ModeCode(0b11111);
2
        let value2 = SubAddress::Value(0b10101);
2

            
2
        let mut word = CommandWord::new().with_subaddress(value1);
2
        assert_eq!(word.subaddress(), value1);
2
        word.set_subaddress(value2);
2
        assert_eq!(word.subaddress(), value2);
2
        assert_eq!(word.as_value(), 0b0000001010100000);
2
    }
    #[test]
2
    fn test_command_get_set_transmit_receive() {
2
        let mut word = CommandWord::new().with_transmit_receive(TransmitReceive::Receive);
2
        assert!(word.transmit_receive().is_receive());
2
        word.set_transmit_receive(TransmitReceive::Transmit);
2
        assert!(word.transmit_receive().is_transmit());
2
    }
    #[test]
2
    fn test_command_get_set_mode_code() {
2
        let mut word = CommandWord::new().with_mode_code(ModeCode::TransmitVectorWord);
2
        assert_eq!(word.mode_code(), ModeCode::TransmitVectorWord);
2
        word.set_mode_code(ModeCode::InitiateSelfTest);
2
        assert_eq!(word.mode_code(), ModeCode::InitiateSelfTest);
2
    }
    #[test]
2
    fn test_command_get_set_word_count() {
2
        let mut word = CommandWord::new().with_word_count(33);
2
        assert_eq!(word.word_count(), 32);
2
        word.set_word_count(5);
2
        assert_eq!(word.word_count(), 5);
2
    }
    #[test]
2
    fn test_command_is_mode_code() {
2
        let mut word = CommandWord::new();
2

            
2
        word.set_subaddress(SubAddress::ModeCode(0b00000));
2
        assert!(word.is_mode_code());
2
        word.set_subaddress(SubAddress::Value(0b01010));
2
        assert!(!word.is_mode_code());
2
        word.set_subaddress(SubAddress::ModeCode(0b11111));
2
        assert!(word.is_mode_code());
2
    }
    #[test]
2
    fn test_command_is_transmit() {
2
        let mut word = CommandWord::new();
2

            
2
        word.set_transmit_receive(TransmitReceive::Transmit);
2
        assert!(word.is_transmit());
2
        word.set_transmit_receive(TransmitReceive::Receive);
2
        assert!(!word.is_transmit());
2
    }
    #[test]
2
    fn test_command_is_receive() {
2
        let mut word = CommandWord::new();
2

            
2
        word.set_transmit_receive(TransmitReceive::Receive);
2
        assert!(word.is_receive());
2
        word.set_transmit_receive(TransmitReceive::Transmit);
2
        assert!(!word.is_receive());
2
    }
    #[test]
2
    fn test_command_count() {
2
        let mut word = CommandWord::new().with_word_count(33);
2
        assert_eq!(word.count(), 32);
2
        word.set_word_count(5);
2
        assert_eq!(word.count(), 5);
2
    }
    #[test]
2
    fn test_command_roundtrip() {
2
        let word1 = CommandWord::from_value(0b0110100001101001);
2
        let data1 = word1.as_bytes();
2

            
2
        let word2 = CommandWord::from_bytes(data1);
2
        let data2 = word2.as_bytes();
2

            
2
        assert_eq!(data1, [0b01101000, 0b01101001]);
2
        assert_eq!(data2, [0b01101000, 0b01101001]);
2
        assert_eq!(word1, word2);
2
    }
    // ----------------------------------------------------------
    // ----------------------------------------------------------
    // CommandWord: Header
    #[test]
2
    fn test_command_header_count() {
2
        let mut word = CommandWord::new().with_word_count(33);
2
        assert_eq!(Header::count(&word), Some(32));
2
        word.set_word_count(5);
2
        assert_eq!(Header::count(&word), Some(5));
2
    }
    // ----------------------------------------------------------
    // ----------------------------------------------------------
    // CommandWord: Word
    #[test]
2
    fn test_command_word_new() {
2
        let word = CommandWord::new();
2
        assert_eq!(word.data, [0, 0]);
2
        assert_eq!(word.parity, 1);
2
    }
    #[test]
2
    fn test_command_word_value() {
2
        let mut word = CommandWord::new().with_value(0b0101010101010101);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_value(), 0b0101010101010101);
2
        word.set_value(0b1010101010101010);
2
        assert_eq!(word.data, [0b10101010, 0b10101010]);
2
        assert_eq!(word.as_value(), 0b1010101010101010);
2
        word = CommandWord::from_value(0b0101010101010101);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_value(), 0b0101010101010101);
2
    }
    #[test]
2
    fn test_command_word_bytes() {
2
        let mut word = CommandWord::new().with_bytes([0b01010101, 0b01010101]);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_bytes(), [0b01010101, 0b01010101]);
2
        word.set_bytes([0b10101010, 0b10101010]);
2
        assert_eq!(word.data, [0b10101010, 0b10101010]);
2
        assert_eq!(word.as_bytes(), [0b10101010, 0b10101010]);
2
        word = CommandWord::from_bytes([0b01010101, 0b01010101]);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_bytes(), [0b01010101, 0b01010101]);
2
    }
    #[test]
2
    fn test_command_word_parity() {
2
        let mut word = CommandWord::from(0).with_parity(0);
2
        assert_eq!(word.parity, 0);
2
        assert_eq!(word.parity(), 0);
2
        assert_eq!(word.check_parity(), false);
2
        word.set_parity(1);
2
        assert_eq!(word.parity, 1);
2
        assert_eq!(word.parity(), 1);
2
        assert_eq!(word.check_parity(), true);
2
        word = CommandWord::from(1).with_calculated_parity();
2
        assert_eq!(word.parity, 0);
2
        assert_eq!(word.parity(), 0);
2
        assert_eq!(word.check_parity(), true);
2
    }
    #[test]
2
    fn test_command_word_build_success() {
2
        let word = CommandWord::new().with_calculated_parity().build();
2
        assert!(word.is_ok());
2
    }
    #[test]
2
    fn test_command_word_build_fail() {
2
        let word = CommandWord::new().with_parity(0).build();
2
        assert!(word.is_err());
2
    }
    // ----------------------------------------------------------
    #[test]
2
    fn test_command_default() {
2
        let word = CommandWord::default();
2
        assert_eq!(word.data, [0, 0]);
2
        assert_eq!(word.parity, 1);
2
    }
    #[test]
2
    fn test_command_from_value() {
2
        let word: CommandWord = 0b1010101010101010.into();
2
        assert_eq!(word.as_value(), 0b1010101010101010);
2
    }
    #[test]
2
    fn test_command_from_bytes() {
2
        let word: CommandWord = [0b10101010, 0b10101010].into();
2
        assert_eq!(word.as_value(), 0b1010101010101010);
2
    }
    #[test]
2
    fn test_command_into_value() {
2
        let word = CommandWord::from(0b1010101010101010);
2
        let value = u16::from(word);
2
        assert_eq!(value, 0b1010101010101010);
2
    }
    #[test]
2
    fn test_command_into_bytes() {
2
        let word = CommandWord::from(0b1010101010101010);
2
        let bytes = <[u8; 2]>::from(word);
2
        assert_eq!(bytes, [0b10101010, 0b10101010]);
2
    }
    // ----------------------------------------------------------
    // StatusWord
    #[test]
2
    fn test_status_get_set_address() {
2
        let item1 = Address::Broadcast(0b11111);
2
        let item2 = Address::Value(0b10101);
2

            
2
        let mut word = StatusWord::new().with_address(item1);
2
        assert_eq!(word.address(), item1);
2
        word.set_address(item2);
2
        assert_eq!(word.address(), item2);
2
        assert_eq!(word.as_value(), 0b1010100000000000);
2
    }
    #[test]
2
    fn test_status_get_set_instrumentation() {
2
        let item1 = Instrumentation::Status;
2
        let item2 = Instrumentation::Command;
2

            
2
        let mut word = StatusWord::new().with_instrumentation(item1);
2
        assert_eq!(word.instrumentation(), item1);
2
        word.set_instrumentation(item2);
2
        assert_eq!(word.instrumentation(), item2);
2
    }
    #[test]
2
    fn test_status_get_set_service_request() {
2
        let item1 = ServiceRequest::NoService;
2
        let item2 = ServiceRequest::Service;
2

            
2
        let mut word = StatusWord::new().with_service_request(item1);
2
        assert_eq!(word.service_request(), item1);
2
        word.set_service_request(item2);
2
        assert_eq!(word.service_request(), item2);
2
    }
    #[test]
2
    fn test_status_get_set_reserved() {
2
        let item1 = Reserved::None;
2
        let item2 = Reserved::Value(0b111);
2

            
2
        let mut word = StatusWord::new().with_reserved(item1);
2
        assert_eq!(word.reserved(), item1);
2
        word.set_reserved(item2);
2
        assert_eq!(word.reserved(), item2);
2
    }
    #[test]
2
    fn test_status_get_set_broadcast_received() {
2
        let item1 = BroadcastReceived::NotReceived;
2
        let item2 = BroadcastReceived::Received;
2

            
2
        let mut word = StatusWord::new().with_broadcast_received(item1);
2
        assert_eq!(word.broadcast_received(), item1);
2
        word.set_broadcast_received(item2);
2
        assert_eq!(word.broadcast_received(), item2);
2
    }
    #[test]
2
    fn test_status_get_set_terminal_busy() {
2
        let item1 = TerminalBusy::NotBusy;
2
        let item2 = TerminalBusy::Busy;
2

            
2
        let mut word = StatusWord::new().with_terminal_busy(item1);
2
        assert_eq!(word.is_busy(), false);
2
        assert_eq!(word.terminal_busy(), item1);
2
        word.set_terminal_busy(item2);
2
        assert_eq!(word.is_busy(), true);
2
        assert_eq!(word.terminal_busy(), item2);
2
    }
    #[test]
2
    fn test_status_get_set_dynamic_bus_acceptance() {
2
        let item1 = DynamicBusAcceptance::NotAccepted;
2
        let item2 = DynamicBusAcceptance::Accepted;
2

            
2
        let mut word = StatusWord::new().with_dynamic_bus_acceptance(item1);
2
        assert_eq!(word.dynamic_bus_acceptance(), item1);
2
        word.set_dynamic_bus_acceptance(item2);
2
        assert_eq!(word.dynamic_bus_acceptance(), item2);
2
    }
    #[test]
2
    fn test_status_get_set_message_error() {
2
        let item1 = MessageError::None;
2
        let item2 = MessageError::Error;
2

            
2
        let mut word = StatusWord::new().with_message_error(item1);
2
        assert_eq!(word.message_error(), item1);
2
        word.set_message_error(item2);
2
        assert_eq!(word.message_error(), item2);
2
    }
    #[test]
2
    fn test_status_get_set_subsystem_error() {
2
        let item1 = SubsystemError::None;
2
        let item2 = SubsystemError::Error;
2

            
2
        let mut word = StatusWord::new().with_subsystem_error(item1);
2
        assert_eq!(word.subsystem_error(), item1);
2
        word.set_subsystem_error(item2);
2
        assert_eq!(word.subsystem_error(), item2);
2
    }
    #[test]
2
    fn test_status_get_set_terminal_error() {
2
        let item1 = TerminalError::None;
2
        let item2 = TerminalError::Error;
2

            
2
        let mut word = StatusWord::new().with_terminal_error(item1);
2
        assert_eq!(word.terminal_error(), item1);
2
        word.set_terminal_error(item2);
2
        assert_eq!(word.terminal_error(), item2);
2
    }
    #[test]
2
    fn test_status_is_error() {
2
        let item1 = TerminalError::Error;
2
        let item2 = SubsystemError::Error;
2
        let item3 = MessageError::Error;
2

            
2
        let mut word1 = StatusWord::new();
2
        let mut word2 = StatusWord::new();
2
        let mut word3 = StatusWord::new();
2

            
2
        assert!(!word1.is_error());
2
        assert!(!word2.is_error());
2
        assert!(!word3.is_error());
2
        word1.set_terminal_error(item1);
2
        word2.set_subsystem_error(item2);
2
        word3.set_message_error(item3);
2

            
2
        assert!(word1.is_error());
2
        assert!(word2.is_error());
2
        assert!(word3.is_error());
2
    }
    #[test]
2
    fn test_status_roundtrip() {
2
        let word1 = StatusWord::from_value(0b0110100001101001);
2
        let data1 = word1.as_bytes();
2

            
2
        let word2 = StatusWord::from_bytes(data1);
2
        let data2 = word2.as_bytes();
2

            
2
        assert_eq!(data1, [0b01101000, 0b01101001]);
2
        assert_eq!(data2, [0b01101000, 0b01101001]);
2
        assert_eq!(word1, word2);
2
    }
    // ----------------------------------------------------------
    // ----------------------------------------------------------
    // StatusWord: Header
    #[test]
2
    fn test_status_header_count() {
2
        let word = StatusWord::new();
2
        assert_eq!(Header::count(&word), None);
2
    }
    // ----------------------------------------------------------
    // ----------------------------------------------------------
    // StatusWord: Word
    #[test]
2
    fn test_status_word_new() {
2
        let word = StatusWord::new();
2
        assert_eq!(word.data, [0, 0]);
2
        assert_eq!(word.parity, 1);
2
    }
    #[test]
2
    fn test_status_word_value() {
2
        let mut word = StatusWord::new().with_value(0b0101010101010101);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_value(), 0b0101010101010101);
2
        word.set_value(0b1010101010101010);
2
        assert_eq!(word.data, [0b10101010, 0b10101010]);
2
        assert_eq!(word.as_value(), 0b1010101010101010);
2
        word = StatusWord::from_value(0b0101010101010101);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_value(), 0b0101010101010101);
2
    }
    #[test]
2
    fn test_status_word_bytes() {
2
        let mut word = StatusWord::new().with_bytes([0b01010101, 0b01010101]);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_bytes(), [0b01010101, 0b01010101]);
2
        word.set_bytes([0b10101010, 0b10101010]);
2
        assert_eq!(word.data, [0b10101010, 0b10101010]);
2
        assert_eq!(word.as_bytes(), [0b10101010, 0b10101010]);
2
        word = StatusWord::from_bytes([0b01010101, 0b01010101]);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_bytes(), [0b01010101, 0b01010101]);
2
    }
    #[test]
2
    fn test_status_word_parity() {
2
        let mut word = StatusWord::from(0).with_parity(0);
2
        assert_eq!(word.parity, 0);
2
        assert_eq!(word.parity(), 0);
2
        assert_eq!(word.check_parity(), false);
2
        word.set_parity(1);
2
        assert_eq!(word.parity, 1);
2
        assert_eq!(word.parity(), 1);
2
        assert_eq!(word.check_parity(), true);
2
        word = StatusWord::from(1).with_calculated_parity();
2
        assert_eq!(word.parity, 0);
2
        assert_eq!(word.parity(), 0);
2
        assert_eq!(word.check_parity(), true);
2
    }
    #[test]
2
    fn test_status_word_build_success() {
2
        let word = StatusWord::new().with_calculated_parity().build();
2
        assert!(word.is_ok());
2
    }
    #[test]
2
    fn test_status_word_build_fail() {
2
        let word = StatusWord::new().with_parity(0).build();
2
        assert!(word.is_err());
2
    }
    // ----------------------------------------------------------
    #[test]
2
    fn test_status_default() {
2
        let word = StatusWord::default();
2
        assert_eq!(word.data, [0, 0]);
2
        assert_eq!(word.parity, 1);
2
    }
    #[test]
2
    fn test_status_from_value() {
2
        let word: StatusWord = 0b1010101010101010.into();
2
        assert_eq!(word.as_value(), 0b1010101010101010);
2
    }
    #[test]
2
    fn test_status_from_bytes() {
2
        let word: StatusWord = [0b10101010, 0b10101010].into();
2
        assert_eq!(word.as_value(), 0b1010101010101010);
2
    }
    #[test]
2
    fn test_status_into_value() {
2
        let word = StatusWord::from(0b1010101010101010);
2
        let value = u16::from(word);
2
        assert_eq!(value, 0b1010101010101010);
2
    }
    #[test]
2
    fn test_status_into_bytes() {
2
        let word = StatusWord::from(0b1010101010101010);
2
        let bytes = <[u8; 2]>::from(word);
2
        assert_eq!(bytes, [0b10101010, 0b10101010]);
2
    }
    // ----------------------------------------------------------
    // DataWord
    #[test]
2
    fn test_data_get_set_string_success() {
2
        let mut word = DataWord::new().with_string("HI").unwrap();
2
        assert_eq!(word.as_bytes(), [0b01001000, 0b01001001]);
2
        assert_eq!(word.as_value(), 0b0100100001001001u16);
2
        assert_eq!(word.as_string(), Ok("HI"));
2
        assert_eq!(word.parity(), 0);
2
        word.set_string("NO").unwrap();
2
        assert_eq!(word.as_bytes(), [0b01001110, 0b01001111]);
2
        assert_eq!(word.as_value(), 0b0100111001001111);
2
        assert_eq!(word.as_string(), Ok("NO"));
2
        assert_eq!(word.parity(), 0);
2
    }
    #[test]
2
    fn test_data_get_set_string_failure() {
2
        let mut word = DataWord::new().with_string("HI").unwrap();
2

            
2
        // fails if string is too long without modifying data
2
        let result = word.set_string("TOO LONG");
2
        assert_eq!(word.as_string(), Ok("HI"));
2
        assert_eq!(word.parity(), 0);
2
        assert!(result.is_err());
        // fails to return a string if not valid utf-8
2
        word.set_value(0b1111111111111111);
2
        assert_eq!(word.as_value(), 0b1111111111111111);
2
        assert!(word.as_string().is_err());
2
        assert_eq!(word.parity(), 1);
2
    }
    #[test]
2
    fn test_data_roundtrip() {
2
        let word1 = DataWord::from_value(0b0110100001101001);
2
        let data1 = word1.as_bytes();
2

            
2
        let word2 = DataWord::from_bytes(data1);
2
        let data2 = word2.as_bytes();
2

            
2
        assert_eq!(data1, [0b01101000, 0b01101001]);
2
        assert_eq!(data2, [0b01101000, 0b01101001]);
2
        assert_eq!(word1, word2);
2
    }
    // ----------------------------------------------------------
    // DataWord: Word
    #[test]
2
    fn test_data_word_new() {
2
        let word = StatusWord::new();
2
        assert_eq!(word.data, [0, 0]);
2
        assert_eq!(word.parity, 1);
2
    }
    #[test]
2
    fn test_data_word_value() {
2
        let mut word = DataWord::new().with_value(0b0101010101010101);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_value(), 0b0101010101010101);
2
        word.set_value(0b1010101010101010);
2
        assert_eq!(word.data, [0b10101010, 0b10101010]);
2
        assert_eq!(word.as_value(), 0b1010101010101010);
2
        word = DataWord::from_value(0b0101010101010101);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_value(), 0b0101010101010101);
2
    }
    #[test]
2
    fn test_data_word_bytes() {
2
        let mut word = DataWord::new().with_bytes([0b01010101, 0b01010101]);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_bytes(), [0b01010101, 0b01010101]);
2
        word.set_bytes([0b10101010, 0b10101010]);
2
        assert_eq!(word.data, [0b10101010, 0b10101010]);
2
        assert_eq!(word.as_bytes(), [0b10101010, 0b10101010]);
2
        word = DataWord::from_bytes([0b01010101, 0b01010101]);
2
        assert_eq!(word.data, [0b01010101, 0b01010101]);
2
        assert_eq!(word.as_bytes(), [0b01010101, 0b01010101]);
2
    }
    #[test]
2
    fn test_data_word_parity() {
2
        let mut word = DataWord::from(0).with_parity(0);
2
        assert_eq!(word.parity, 0);
2
        assert_eq!(word.parity(), 0);
2
        assert_eq!(word.check_parity(), false);
2
        word.set_parity(1);
2
        assert_eq!(word.parity, 1);
2
        assert_eq!(word.parity(), 1);
2
        assert_eq!(word.check_parity(), true);
2
        word = DataWord::from(1).with_calculated_parity();
2
        assert_eq!(word.parity, 0);
2
        assert_eq!(word.parity(), 0);
2
        assert_eq!(word.check_parity(), true);
2
    }
    #[test]
2
    fn test_data_build_success() {
2
        let word = DataWord::new().with_calculated_parity().build();
2
        assert!(word.is_ok());
2
    }
    #[test]
2
    fn test_data_build_fail() {
2
        let word = DataWord::new().with_parity(0).build();
2
        assert!(word.is_err());
2
    }
    // ----------------------------------------------------------
    #[test]
2
    fn test_data_default() {
2
        let word = DataWord::default();
2
        assert_eq!(word.data, [0, 0]);
2
        assert_eq!(word.parity, 1);
2
    }
    #[test]
2
    fn test_data_try_from_string_success() {
2
        let result = DataWord::try_from("HI");
2
        assert!(result.is_ok());
2
    }
    #[test]
2
    fn test_data_try_from_string_fail() {
2
        let result = DataWord::try_from("TOO LONG");
2
        assert!(result.is_err());
2
    }
    #[test]
2
    fn test_data_from_value() {
2
        let word: DataWord = 0b1010101010101010.into();
2
        assert_eq!(word.as_value(), 0b1010101010101010);
2
    }
    #[test]
2
    fn test_data_from_bytes() {
2
        let word: DataWord = [0b10101010, 0b10101010].into();
2
        assert_eq!(word.as_value(), 0b1010101010101010);
2
    }
    #[test]
2
    fn test_data_into_value() {
2
        let word = DataWord::from(0b1010101010101010);
2
        let value = u16::from(word);
2
        assert_eq!(value, 0b1010101010101010);
2
    }
    #[test]
2
    fn test_data_into_bytes() {
2
        let word = DataWord::from(0b1010101010101010);
2
        let bytes = <[u8; 2]>::from(word);
2
        assert_eq!(bytes, [0b10101010, 0b10101010]);
2
    }
    #[test]
2
    fn test_data_into_u32() {
2
        let word = DataWord::from(0b0000000010101010);
2
        let value = u32::from(word);
2
        assert_eq!(value, 170); // decimal
2
    }
    #[test]
2
    fn test_data_into_u64() {
2
        let word = DataWord::from(0b0000000010101010);
2
        let value = u64::from(word);
2
        assert_eq!(value, 170); // decimal
2
    }
    #[test]
2
    fn test_data_into_i16() {
2
        let word = DataWord::from(0b0000000010101010);
2
        let value = i16::from(word);
2
        assert_eq!(value, 170); // decimal
2
    }
    #[test]
2
    fn test_data_into_i32() {
2
        let word = DataWord::from(0b0000000010101010);
2
        let value = i32::from(word);
2
        assert_eq!(value, 170); // decimal
2
    }
    #[test]
2
    fn test_data_into_i64() {
2
        let word = DataWord::from(0b0000000010101010);
2
        let value = i64::from(word);
2
        assert_eq!(value, 170); // decimal
2
    }
}