1
use crate::word::WordType;
2
use crate::word::{CommandWord, DataWord, StatusWord};
3
use crate::{errors::*, Header, Packet, Word};
4

            
5
/// Default value for word array
6
const ARRAY_NONE: WordType = WordType::None;
7

            
8
/// A message sent between two terminals on the bus
9
///
10
/// The Message struct does very minimal message validation
11
/// for the message structure:
12
///
13
/// * Command or status words are always the first word.
14
/// * Data words are limited based on the command word count.
15
/// * For status words, data words are parsed to the end of the buffer
16
///
17
/// Messages do not validate larger messaging patterns that
18
/// require context about previous messages or terminal type.
19
///
20
/// ## Example
21
///
22
/// ```rust
23
/// # use mil_std_1553b::*;
24
/// # fn main() -> Result<()> {
25
///     let message= Message::<3>::new()
26
///         .with_command(CommandWord::new()
27
///             .with_address(Address::Value(12))
28
///             .with_subaddress(SubAddress::Value(5))
29
///             .with_word_count(2)
30
///             .build()?
31
///         )
32
///         .with_data(DataWord::new())
33
///         .with_data(DataWord::new())
34
///         .build()?;
35
///
36
///     assert!(message.is_full());
37
///     assert_eq!(message.length(),3);
38
///     assert_eq!(message.count(),2);
39
/// # Ok(())
40
/// # }
41
/// ```
42
///
43
#[derive(Clone, Eq, PartialEq, Debug)]
44
pub struct Message<const WORDS: usize = 33> {
45
    words: [WordType; WORDS],
46
    error: Option<Error>,
47
}
48

            
49
impl<const WORDS: usize> Message<WORDS> {
50
    /// Create a new message struct
51
110
    pub fn new() -> Self {
52
110
        Self {
53
110
            words: [ARRAY_NONE; WORDS],
54
110
            error: None,
55
110
        }
56
110
    }
57

            
58
    /// Constructor method to set the message body from a string
59
    ///
60
    /// See [set_string][Self::set_string] for more information.
61
    ///
62
    /// # Arguments
63
    ///
64
    /// * `data` - String to include
65
    ///
66
10
    pub fn with_string(mut self, data: &str) -> Self {
67
10
        self.set_string(data);
68
10
        self
69
10
    }
70

            
71
    /// Constructor method to set the message body from bytes
72
    ///
73
    /// See [set_bytes][Self::set_bytes] for more information.
74
    ///
75
    /// # Arguments
76
    ///
77
    /// * `data` - Bytes to include
78
    ///
79
10
    pub fn with_bytes(mut self, data: &[u8]) -> Self {
80
10
        self.set_bytes(data);
81
10
        self
82
10
    }
83

            
84
    /// Constructor method to add a command word to the message
85
    ///
86
    /// # Arguments
87
    ///
88
    /// * `word` - A word to add
89
    ///
90
70
    pub fn with_command<T: Into<CommandWord>>(mut self, word: T) -> Self {
91
70
        self.add_command(word.into());
92
70
        self
93
70
    }
94

            
95
    /// Constructor method to add a status word to the message
96
    ///
97
    /// # Arguments
98
    ///
99
    /// * `word` - A word to add
100
    ///
101
24
    pub fn with_status<T: Into<StatusWord>>(mut self, word: T) -> Self {
102
24
        self.add_status(word.into());
103
24
        self
104
24
    }
105

            
106
    /// Constructor method to add a data word to the message
107
    ///
108
    /// # Arguments
109
    ///
110
    /// * `word` - A word to add
111
    ///
112
42
    pub fn with_data<T: Into<DataWord>>(mut self, word: T) -> Self {
113
42
        self.add_data(word.into());
114
42
        self
115
42
    }
116

            
117
    /// Constructor method to add a word to the message
118
    ///
119
    /// # Arguments
120
    ///
121
    /// * `word` - A word to add
122
    ///
123
18
    pub fn with_word<T: Word>(mut self, word: T) -> Self {
124
18
        self.add(word);
125
18
        self
126
18
    }
127

            
128
    /// Method to finalize construction
129
    ///
130
    /// Performs basic checks for message validity, returning
131
    /// an error:
132
    ///
133
    /// * If the wrong number of words were added during construction
134
    /// * If there are multiple header words (command or status)
135
    /// * If any word has a bad parity
136
    /// * If the first word is a data word
137
    ///
138
66
    pub fn build(self) -> Result<Self> {
139
66
        self.validate().map(|_| self)
140
66
    }
141

            
142
    /// Parse a slice of bytes into a command message
143
    ///
144
    /// This method interpretes the byte array as a series
145
    /// of 20-bit long words, beginning with a command word.
146
    /// The word count of the parsed command will determine
147
    /// how many data words are parsed.
148
    ///
149
    /// Each word is a triplet containing 3-bit sync, 16-bit word,
150
    /// and 1-bit parity. It is assumed that the message
151
    /// being parsed is aligned to the beginning of the slice
152
    /// (the leftmost three bits of the first byte are the sync
153
    /// field of the command word).
154
    ///
155
    /// # Arguments
156
    ///
157
    /// * `data` - A slice of bytes to parse
158
    ///
159
    /// ## Example
160
    ///
161
    /// ```rust
162
    /// # use mil_std_1553b::*;
163
    /// # fn main() -> Result<()> {
164
    ///     let message = Message::<2>::read_command(&[
165
    ///         0b10000011,
166
    ///         0b00001100,
167
    ///         0b00100010,
168
    ///         0b11010000,
169
    ///         0b11010010
170
    ///     ])?;
171
    ///
172
    ///     assert!(message.is_full());
173
    ///     assert!(message.is_command());
174
    ///     assert_eq!(message.length(),2);
175
    ///     assert_eq!(message.count(),1);
176
    /// # Ok(())
177
    /// # }
178
6
    pub fn read_command(data: &[u8]) -> Result<Self> {
179
6
        Self::read::<CommandWord>(data)
180
6
    }
181

            
182
    /// Parse a slice of bytes into a status message
183
    ///
184
    /// This method interpretes the byte array as a series
185
    /// of 20-bit long words, starting with a status word.
186
    /// Because status words do not have a word count field,
187
    /// this method will parse data words to the end of the
188
    /// byte array. Slice the input data to avoid parsing
189
    /// any unwanted words.
190
    ///
191
    /// It is assumed that the message being parsed is aligned
192
    /// to the beginning of the slice (the leftmost three bits
193
    /// of the first byte are the sync field of the status word).
194
    ///
195
    /// # Arguments
196
    ///
197
    /// * `data` - A slice of bytes to parse
198
    ///
199
    /// See [read_command][Message::read_command] for more information.
200
    ///
201
    /// ## Example
202
    ///
203
    /// ```rust
204
    /// # use mil_std_1553b::*;
205
    /// # fn main() -> Result<()> {
206
    ///     let message = Message::<2>::read_status(&[
207
    ///         0b10000011,
208
    ///         0b00001100,
209
    ///         0b00100010,
210
    ///         0b11010000,
211
    ///         0b11010010
212
    ///     ])?;
213
    ///
214
    ///     assert!(message.is_full());
215
    ///     assert!(message.is_status());
216
    ///     assert_eq!(message.length(),2);
217
    ///     assert_eq!(message.count(),1);
218
    ///     
219
    /// # Ok(())
220
    /// # }
221
    /// ```
222
8
    pub fn read_status(data: &[u8]) -> Result<Self> {
223
8
        Self::read::<StatusWord>(data)
224
8
    }
225

            
226
    /// Get the command word from the message
227
    ///
228
    /// Returns `None` if this message doesn't
229
    /// have a command word.
230
    ///
231
    /// # Arguments
232
    ///
233
    /// * `index` - An index
234
    ///
235
128
    pub fn command(&self) -> Option<&CommandWord> {
236
128
        if let Some(WordType::Command(w)) = &self.words.first() {
237
108
            Some(w)
238
        } else {
239
20
            None
240
        }
241
128
    }
242

            
243
    /// Get the status word from the message
244
    ///
245
    /// Returns `None` if this message doesn't
246
    /// have a status word.
247
    ///
248
    /// # Arguments
249
    ///
250
    /// * `index` - An index
251
    ///
252
42
    pub fn status(&self) -> Option<&StatusWord> {
253
42
        if let Some(WordType::Status(w)) = &self.words.first() {
254
4
            Some(w)
255
        } else {
256
38
            None
257
        }
258
42
    }
259

            
260
    /// Get a data word from the message by index
261
    ///
262
    /// An index of 0 will return the first *data word*, not
263
    /// the leading command or status word.
264
    ///
265
    /// # Arguments
266
    ///
267
    /// * `index` - An index
268
    ///
269
8
    pub fn at(&self, index: usize) -> Option<&DataWord> {
270
8
        if let Some(WordType::Data(w)) = &self.words.get(index + 1) {
271
6
            Some(w)
272
        } else {
273
2
            None
274
        }
275
8
    }
276

            
277
    /// Get a custom data word from the message by index
278
    ///
279
    /// An index of 0 will return the first *data word*, not
280
    /// the leading command or status word.
281
    ///
282
    /// # Arguments
283
    ///
284
    /// * `index` - An index
285
    ///
286
40
    pub fn get<'a, T>(&'a self, index: usize) -> Option<T>
287
40
    where
288
40
        T: TryFrom<&'a DataWord>,
289
40
    {
290
40
        if let Some(WordType::Data(w)) = &self.words.get(index + 1) {
291
34
            T::try_from(w).ok()
292
        } else {
293
6
            None
294
        }
295
40
    }
296

            
297
    /// Add a word to the message
298
    ///
299
    /// # Arguments
300
    ///
301
    /// * `word` - A word to add
302
    ///
303
270
    pub fn add<T: Word>(&mut self, word: T) {
304
270
        let index = self
305
270
            .words
306
270
            .iter()
307
270
            .position(WordType::is_none)
308
270
            .unwrap_or(self.words.len());
309
270

            
310
270
        if index < self.words.len() {
311
242
            self.words[index] = word.into();
312
242
        } else {
313
28
            self.error = Some(Error::OutOfBounds);
314
28
        }
315
270
    }
316

            
317
    /// Add words from a string
318
    ///
319
    /// This method breaks the string into two-byte
320
    /// chunks and adds them as [DataWord]s to the
321
    /// message. If it fails, [is_valid][Self::is_valid] will
322
    /// return false and [validate][Self::validate] will
323
    /// return an error.
324
    ///
325
    /// # Arguments
326
    ///
327
    /// * `data` - Words to add
328
    ///
329
30
    pub fn add_string(&mut self, data: &str) {
330
50
        for chunk in data.as_bytes().chunks(2).map(|s| match s.len() {
331
48
            2 => [s[0], s[1]],
332
2
            1 => [s[0], 0],
333
            _ => [0, 0],
334
50
        }) {
335
50
            self.add_data(chunk.into());
336
50
        }
337
30
    }
338

            
339
    /// Add words from bytes
340
    ///
341
    /// This method breaks the given bytes into two-byte
342
    /// chunks and adds them as [DataWord]s to the
343
    /// message. If it fails, [is_valid][Self::is_valid] will
344
    /// return false and [validate][Self::validate] will
345
    /// return an error.
346
    ///
347
    /// **Given data should only contain the words,
348
    /// without sync or parity bits.**
349
    ///
350
    /// # Arguments
351
    ///
352
    /// * `data` - Words to add
353
    ///
354
30
    pub fn add_bytes(&mut self, data: &[u8]) {
355
50
        for chunk in data.chunks(2).map(|s| match s.len() {
356
48
            2 => [s[0], s[1]],
357
2
            1 => [s[0], 0],
358
            _ => [0, 0],
359
50
        }) {
360
50
            self.add_data(chunk.into());
361
50
        }
362
30
    }
363

            
364
    /// Add a data word
365
    ///
366
    /// # Arguments
367
    ///
368
    /// * `word` - A word to add
369
    ///
370
158
    pub fn add_data(&mut self, word: DataWord) {
371
158
        self.add(word);
372
158
    }
373

            
374
    /// Add a status word
375
    ///
376
    /// # Arguments
377
    ///
378
    /// * `word` - A word to add
379
    ///
380
24
    pub fn add_status(&mut self, word: StatusWord) {
381
24
        self.add(word);
382
24
    }
383

            
384
    /// Add a command word
385
    ///
386
    /// # Arguments
387
    ///
388
    /// * `word` - A word to add
389
    ///
390
70
    pub fn add_command(&mut self, word: CommandWord) {
391
70
        self.add(word);
392
70
    }
393

            
394
    /// Set words from a string
395
    ///
396
    /// This method overwrites existing data in the
397
    /// message by breaking the given string into two-byte
398
    /// chunks and adding them as [DataWord]s. If it fails,
399
    /// [is_valid][Self::is_valid] will return false and
400
    /// [validate][Self::validate] will return an error.
401
    ///
402
    /// # Arguments
403
    ///
404
    /// * `data` - Words to add
405
    ///
406
16
    pub fn set_string(&mut self, data: &str) {
407
16
        self.words[1..].fill(WordType::None);
408
16
        self.add_string(data);
409
16
    }
410

            
411
    /// Set words from bytes
412
    ///
413
    /// This method overwrites existing data in the
414
    /// message by breaking the given string into two-byte
415
    /// chunks and adding them as [DataWord]s. If it fails,
416
    /// [is_valid][Self::is_valid] will return false and
417
    /// [validate][Self::validate] will return an error.
418
    ///
419
    /// **Given data should only contain the words,
420
    /// without sync or parity bits.**
421
    ///
422
    /// # Arguments
423
    ///
424
    /// * `data` - Words to add
425
    ///
426
16
    pub fn set_bytes(&mut self, data: &[u8]) {
427
16
        self.words[1..].fill(WordType::None);
428
16
        self.add_bytes(data);
429
16
    }
430

            
431
    /// Check if message starts with a command word
432
    #[must_use = "Returned value is not used"]
433
40
    pub fn is_command(&self) -> bool {
434
40
        self.command().is_some()
435
40
    }
436

            
437
    /// Check if message starts with a status word
438
    #[must_use = "Returned value is not used"]
439
40
    pub fn is_status(&self) -> bool {
440
40
        self.status().is_some()
441
40
    }
442

            
443
    /// Check if the message is full
444
    ///
445
    /// This method will return false for status messages
446
    /// until the maximum number of data words has been reached.
447
    #[must_use = "Returned value is not used"]
448
26
    pub fn is_full(&self) -> bool {
449
26
        if let Some(w) = self.command() {
450
22
            self.count() == w.count()
451
        } else {
452
4
            self.length() == self.size()
453
        }
454
26
    }
455

            
456
    /// Check if the message is empty
457
    #[must_use = "Returned value is not used"]
458
2
    pub fn is_empty(&self) -> bool {
459
2
        self.length() == 0
460
2
    }
461

            
462
    /// Check if the message is valid
463
    #[must_use = "Returned value is not used"]
464
32
    pub fn is_valid(&self) -> bool {
465
32
        self.validate().is_ok()
466
32
    }
467

            
468
    /// Method to validate message
469
    ///
470
    /// Performs basic checks for message validity, returning
471
    /// an error:
472
    ///
473
    /// * If and error was generated during construction
474
    /// * If there are multiple header words (command or status)
475
    /// * If any word has a bad parity
476
    /// * If the first word is a data word
477
    ///
478
98
    pub fn validate(&self) -> Result<()> {
479
        // fail if an error is set
480
98
        if let Some(e) = self.error {
481
28
            return Err(e);
482
70
        }
483
70

            
484
70
        // fail if there are multiple header words
485
70
        if self.count() != (self.length() - 1) {
486
6
            return Err(Error::InvalidWord);
487
64
        }
488
64

            
489
64
        // fail if any word has a bad parity bit
490
150
        if self.words.iter().any(|w| !w.check_parity()) {
491
4
            return Err(Error::InvalidWord);
492
60
        }
493
60

            
494
60
        // fail if the first word is a data word
495
60
        if self.words.first().map(|w| w.is_data()).unwrap_or(false) {
496
4
            return Err(Error::HeaderNotFirst);
497
56
        }
498

            
499
        // fail if there are multiple header words
500
56
        if let Some(w) = self.command() {
501
44
            if w.count() != self.count() {
502
4
                return Err(Error::InvalidMessage);
503
40
            }
504
12
        }
505

            
506
52
        Ok(())
507
98
    }
508

            
509
    /// Clear all words from the message
510
2
    pub fn clear(&mut self) {
511
2
        self.words = [ARRAY_NONE; WORDS];
512
2
        self.error = None;
513
2
    }
514

            
515
    /// Get the current number of data words
516
188
    pub fn count(&self) -> usize {
517
574
        self.words.iter().filter(|w| w.is_data()).count()
518
188
    }
519

            
520
    /// Get the current number of words
521
150
    pub fn length(&self) -> usize {
522
492
        self.words.iter().filter(|w| w.is_some()).count()
523
150
    }
524

            
525
    /// Get the total possible size of the message
526
60
    pub fn size(&self) -> usize {
527
60
        self.words.len()
528
60
    }
529

            
530
    /// Get expected number of data words
531
4
    pub fn limit(&self) -> usize {
532
4
        self.command()
533
4
            .map(CommandWord::count)
534
4
            .unwrap_or(self.size().saturating_sub(1))
535
4
    }
536

            
537
    /// Read bytes as a message
538
    ///
539
    /// # Arguments
540
    ///
541
    /// * `data` - A slice of bytes to read
542
    ///
543
14
    pub fn read<T: Word + Header>(data: &[u8]) -> Result<Self> {
544
14
        let min = 3;
545
14

            
546
14
        // need at least three bytes to parse
547
14
        if data.len() < min {
548
2
            return Err(Error::InvalidMessage);
549
12
        }
550
12

            
551
12
        // estimate word count from given data
552
12
        let estimate = ((data.len() * 8) / 20).saturating_sub(1);
553

            
554
        // parse the specified header word
555
12
        let word = Packet::read(data, 0)?.as_word::<T>()?;
556

            
557
        // get the number of expected words or an
558
        // estimate if the header is a status word.
559
12
        let count = word.count().unwrap_or(estimate);
560
12

            
561
12
        // the expected number of bytes to parse
562
12
        let expected = (((count + 1) * 20) + 7) / 8;
563
12

            
564
12
        // return error if data is too small
565
12
        if data.len() < expected {
566
2
            return Err(Error::InvalidMessage);
567
10
        }
568
10

            
569
10
        // create a new message with the header word
570
10
        let mut message = Self::new().with_word(word);
571
10

            
572
10
        let start = 1; // skip the service word
573
10
        let end = count + 1; // adjust for service word
574

            
575
16
        for index in start..end {
576
16
            let b = index * 20; // offset in bits
577
16
            let i = b / 8; // byte offset (whole)
578
16
            let o = b % 8; // byte offset (fraction)
579
16
            let bytes = &data[i..];
580
16

            
581
16
            // use a packet to parse the bytes and convert to a word
582
16
            message.add_data(Packet::read(bytes, o)?.try_into()?);
583
        }
584

            
585
10
        Ok(message)
586
14
    }
587

            
588
    /// Write the message to a byte array
589
    ///
590
    /// # Arguments
591
    ///
592
    /// * `data` - A slice of bytes to write
593
    ///
594
12
    pub fn write(&self, data: &mut [u8]) -> Result<()> {
595
12
        let count = ((self.length() * 20) + 7) / 8;
596
12

            
597
12
        if data.len() < count {
598
4
            return Err(Error::OutOfBounds);
599
8
        }
600

            
601
28
        for (index, word) in self.words.iter().take_while(|w| w.is_some()).enumerate() {
602
24
            let b = index * 20;
603
24
            let i = b / 8;
604
24
            let o = b % 8;
605

            
606
24
            let packet = Packet::try_from(word)?;
607
24
            packet.write(&mut data[i..], o)?;
608
        }
609

            
610
8
        Ok(())
611
12
    }
612
}
613

            
614
impl Default for Message {
615
2
    fn default() -> Self {
616
2
        Self::new()
617
2
    }
618
}
619

            
620
#[cfg(test)]
621
mod tests {
622
    use super::*;
623

            
624
    #[test]
625
2
    fn test_message_with_string_0() {
626
2
        let message = Message::<3>::new()
627
2
            .with_command(0b0000000000000010)
628
2
            .with_string("TEST")
629
2
            .build()
630
2
            .unwrap();
631
2
        assert!(message.is_full());
632
2
        assert_eq!(message.length(), 3);
633
2
        assert_eq!(message.count(), 2);
634
2
        assert_eq!(message.size(), 3);
635
2
        assert!(message.is_command());
636
2
        assert!(!message.is_status());
637
2
    }
638

            
639
    #[test]
640
2
    fn test_message_with_string_1() {
641
2
        let message = Message::<2>::new()
642
2
            .with_command(0b0000000000000010)
643
2
            .with_string("TEST")
644
2
            .build();
645
2

            
646
2
        // error because the string was too long
647
2
        // for the given Message
648
2
        assert!(message.is_err());
649
2
    }
650

            
651
    #[test]
652
2
    fn test_message_with_string_2() {
653
2
        let message = Message::<3>::new()
654
2
            .with_command(0b0000000000000001)
655
2
            .with_string("TEST")
656
2
            .build();
657
2

            
658
2
        // error because the string was too long
659
2
        // for the command data word count
660
2
        assert!(message.is_err());
661
2
    }
662

            
663
    #[test]
664
2
    fn test_message_with_string_3() {
665
2
        let message = Message::<2>::new()
666
2
            .with_status(0b0000000000000000)
667
2
            .with_string("TEST")
668
2
            .build();
669
2

            
670
2
        // error because the string was too long
671
2
        // for the given Message
672
2
        assert!(message.is_err());
673
2
    }
674

            
675
    #[test]
676
2
    fn test_message_with_string_4() {
677
2
        let message = Message::<3>::new()
678
2
            .with_command(0b0000000000000010)
679
2
            .with_string("TES")
680
2
            .build()
681
2
            .unwrap();
682
2

            
683
2
        // The character will be interpreted as
684
2
        // zero because it wasn't given.
685
2
        assert!(message.is_full());
686
2
        assert_eq!(message.length(), 3);
687
2
        assert_eq!(message.count(), 2);
688
2
        assert_eq!(message.size(), 3);
689
2
        assert!(message.is_command());
690
2
        assert!(!message.is_status());
691
2
    }
692

            
693
    #[test]
694
2
    fn test_message_with_bytes_0() {
695
2
        let message = Message::<3>::new()
696
2
            .with_command(0b0000000000000010)
697
2
            .with_bytes(&[1, 2, 3, 4])
698
2
            .build()
699
2
            .unwrap();
700
2
        assert!(message.is_full());
701
2
        assert_eq!(message.length(), 3);
702
2
        assert_eq!(message.count(), 2);
703
2
        assert_eq!(message.size(), 3);
704
2
        assert!(message.is_command());
705
2
        assert!(!message.is_status());
706
2
    }
707

            
708
    #[test]
709
2
    fn test_message_with_bytes_1() {
710
2
        let message = Message::<2>::new()
711
2
            .with_command(0b0000000000000010)
712
2
            .with_bytes(&[1, 2, 3, 4])
713
2
            .build();
714
2

            
715
2
        // error because too many bytes
716
2
        // for the given Message
717
2
        assert!(message.is_err());
718
2
    }
719

            
720
    #[test]
721
2
    fn test_message_with_bytes_2() {
722
2
        let message = Message::<3>::new()
723
2
            .with_command(0b0000000000000001)
724
2
            .with_bytes(&[1, 2, 3, 4])
725
2
            .build();
726
2

            
727
2
        // error because too many bytes
728
2
        // for the command data word count
729
2
        assert!(message.is_err());
730
2
    }
731

            
732
    #[test]
733
2
    fn test_message_with_bytes_3() {
734
2
        let message = Message::<2>::new()
735
2
            .with_status(0b0000000000000000)
736
2
            .with_bytes(&[1, 2, 3, 4])
737
2
            .build();
738
2

            
739
2
        // error because too many bytes
740
2
        // for the given Message
741
2
        assert!(message.is_err());
742
2
    }
743

            
744
    #[test]
745
2
    fn test_message_with_bytes_4() {
746
2
        let message = Message::<3>::new()
747
2
            .with_command(0b0000000000000010)
748
2
            .with_bytes(&[1, 2, 3])
749
2
            .build()
750
2
            .unwrap();
751
2

            
752
2
        // The last byte of the second word will be
753
2
        // zero because it wasn't given.
754
2
        assert!(message.is_full());
755
2
        assert_eq!(message.length(), 3);
756
2
        assert_eq!(message.count(), 2);
757
2
        assert_eq!(message.size(), 3);
758
2
        assert!(message.is_command());
759
2
        assert!(!message.is_status());
760
2
    }
761

            
762
    #[test]
763
2
    fn test_message_set_string_command_0() {
764
2
        let mut message = Message::<2>::new().with_command(0b0000000000000001);
765
2

            
766
2
        message.add_string("TE");
767
2
        let string1 = message.get(0);
768
2
        assert_eq!(string1, Some("TE"));
769

            
770
2
        message.set_string("ST");
771
2
        let string2 = message.get(0);
772
2
        assert_eq!(string2, Some("ST"));
773

            
774
2
        assert!(message.is_valid());
775
2
        assert!(message.is_full());
776
2
        assert_eq!(message.length(), 2);
777
2
        assert_eq!(message.count(), 1);
778
2
        assert_eq!(message.size(), 2);
779
2
        assert!(message.is_command());
780
2
        assert!(!message.is_status());
781
2
    }
782

            
783
    #[test]
784
2
    fn test_message_set_string_command_1() {
785
2
        let mut message = Message::<3>::new().with_command(0b0000000000000010);
786
2

            
787
2
        message.add_string("TEST");
788
2
        let string1 = message.get(0);
789
2
        let string2 = message.get(1);
790
2
        assert_eq!(string1, Some("TE"));
791
2
        assert_eq!(string2, Some("ST"));
792

            
793
2
        message.set_string("TSET");
794
2
        let string1 = message.get(0);
795
2
        let string2 = message.get(1);
796
2
        assert_eq!(string1, Some("TS"));
797
2
        assert_eq!(string2, Some("ET"));
798

            
799
2
        assert!(message.is_valid());
800
2
        assert_eq!(message.length(), 3);
801
2
        assert_eq!(message.count(), 2);
802
2
        assert_eq!(message.size(), 3);
803
2
        assert!(message.is_command());
804
2
        assert!(!message.is_status());
805
2
    }
806

            
807
    #[test]
808
2
    fn test_message_set_string_command_2() {
809
2
        let mut message = Message::<2>::new().with_command(0b0000000000000001);
810
2

            
811
2
        message.set_string("TEST");
812
2

            
813
2
        let string1 = message.get::<&str>(0);
814
2
        let string2 = message.get::<&str>(1);
815
2

            
816
2
        assert_eq!(string1, Some("TE"));
817
2
        assert_eq!(string2, None);
818

            
819
        // failed because the given string is too long
820
        // to fit in a message with size 2
821
2
        assert!(!message.is_valid());
822

            
823
2
        assert_eq!(message.length(), 2);
824
2
        assert_eq!(message.count(), 1);
825
2
        assert_eq!(message.size(), 2);
826
2
        assert!(message.is_command());
827
2
        assert!(!message.is_status());
828
2
    }
829

            
830
    #[test]
831
2
    fn test_message_set_bytes_command_0() {
832
2
        let mut message = Message::<2>::new().with_command(0b0000000000000001);
833
2

            
834
2
        message.add_bytes(&[1, 2]);
835
2
        let bytes1 = message.get(0);
836
2
        assert_eq!(bytes1, Some([1, 2]));
837

            
838
2
        message.set_bytes(&[2, 1]);
839
2
        let bytes2 = message.get(0);
840
2
        assert_eq!(bytes2, Some([2, 1]));
841

            
842
2
        assert!(message.is_valid());
843
2
        assert!(message.is_full());
844
2
        assert_eq!(message.length(), 2);
845
2
        assert_eq!(message.count(), 1);
846
2
        assert_eq!(message.size(), 2);
847
2
        assert!(message.is_command());
848
2
        assert!(!message.is_status());
849
2
    }
850

            
851
    #[test]
852
2
    fn test_message_set_bytes_command_1() {
853
2
        let mut message = Message::<3>::new().with_command(0b0000000000000010);
854
2

            
855
2
        message.set_bytes(&[1, 2, 3, 4]);
856
2
        let bytes1 = message.get(0);
857
2
        let bytes2 = message.get(1);
858
2
        assert_eq!(bytes1, Some([1, 2]));
859
2
        assert_eq!(bytes2, Some([3, 4]));
860

            
861
2
        message.set_bytes(&[4, 3, 2, 1]);
862
2
        let bytes1 = message.get(0);
863
2
        let bytes2 = message.get(1);
864
2
        assert_eq!(bytes1, Some([4, 3]));
865
2
        assert_eq!(bytes2, Some([2, 1]));
866

            
867
2
        assert!(message.is_valid());
868
2
        assert_eq!(message.length(), 3);
869
2
        assert_eq!(message.count(), 2);
870
2
        assert_eq!(message.size(), 3);
871
2
        assert!(message.is_command());
872
2
        assert!(!message.is_status());
873
2
    }
874

            
875
    #[test]
876
2
    fn test_message_set_bytes_command_2() {
877
2
        let mut message = Message::<2>::new().with_command(0b0000000000000001);
878
2

            
879
2
        message.add_bytes(&[1, 2, 3, 4]);
880
2

            
881
2
        let string1 = message.get::<[u8; 2]>(0);
882
2
        let string2 = message.get::<[u8; 2]>(1);
883
2

            
884
2
        assert_eq!(string1, Some([1, 2]));
885
2
        assert_eq!(string2, None);
886

            
887
        // failed because the given string is too long
888
        // to fit in a message with size 2
889
2
        assert!(!message.is_valid());
890

            
891
2
        assert_eq!(message.length(), 2);
892
2
        assert_eq!(message.count(), 1);
893
2
        assert_eq!(message.size(), 2);
894
2
        assert!(message.is_command());
895
2
        assert!(!message.is_status());
896
2
    }
897

            
898
    #[test]
899
2
    fn test_message_add_string_command_0() {
900
2
        // build a command message with word count 1
901
2
        let mut message = Message::<2>::new().with_command(0b0000000000000001);
902
2

            
903
2
        message.add_string("TE");
904
2

            
905
2
        assert!(message.is_valid());
906
2
        assert!(message.is_full());
907
2
        assert_eq!(message.length(), 2);
908
2
        assert_eq!(message.count(), 1);
909
2
        assert_eq!(message.size(), 2);
910
2
        assert!(message.is_command());
911
2
        assert!(!message.is_status());
912
2
    }
913

            
914
    #[test]
915
2
    fn test_message_add_string_command_1() {
916
2
        // build a command message with word count 1
917
2
        let mut message = Message::<2>::new().with_command(0b0000000000000001);
918
2

            
919
2
        message.add_string("TE");
920
2
        message.add_string("ST");
921
2

            
922
2
        // failed because the message only has enough space
923
2
        // for two characters (one data word), but two were given.
924
2
        assert!(!message.is_valid());
925

            
926
2
        assert!(message.is_full());
927
2
        assert_eq!(message.length(), 2);
928
2
        assert_eq!(message.count(), 1);
929
2
        assert_eq!(message.size(), 2);
930
2
        assert!(message.is_command());
931
2
        assert!(!message.is_status());
932
2
    }
933

            
934
    #[test]
935
2
    fn test_message_add_string_command_2() {
936
2
        // build a command message with word count 1
937
2
        let mut message = Message::<2>::new().with_command(0b0000000000000001);
938
2

            
939
2
        message.add_string("TEST");
940
2

            
941
2
        // failed because the given string is too long
942
2
        // to fit in a message with size 2
943
2
        assert!(!message.is_valid());
944

            
945
2
        assert_eq!(message.length(), 2);
946
2
        assert_eq!(message.count(), 1);
947
2
        assert_eq!(message.size(), 2);
948
2
        assert!(message.is_command());
949
2
        assert!(!message.is_status());
950
2
    }
951

            
952
    #[test]
953
2
    fn test_message_add_string_command_3() {
954
2
        // build a command message with word count 2
955
2
        let mut message = Message::<3>::new().with_command(0b0000000000000010);
956
2

            
957
2
        message.add_string("TEST");
958
2

            
959
2
        assert!(message.is_valid());
960
2
        assert_eq!(message.length(), 3);
961
2
        assert_eq!(message.count(), 2);
962
2
        assert_eq!(message.size(), 3);
963
2
        assert!(message.is_command());
964
2
        assert!(!message.is_status());
965
2
    }
966

            
967
    #[test]
968
2
    fn test_message_add_bytes_command_0() {
969
2
        // build a command message with word count 1
970
2
        let mut message = Message::<2>::new().with_command(0b0000000000000001);
971
2

            
972
2
        message.add_bytes(&[1, 2]);
973
2

            
974
2
        assert!(message.is_valid());
975
2
        assert!(message.is_full());
976
2
        assert_eq!(message.length(), 2);
977
2
        assert_eq!(message.count(), 1);
978
2
        assert_eq!(message.size(), 2);
979
2
        assert!(message.is_command());
980
2
        assert!(!message.is_status());
981
2
    }
982

            
983
    #[test]
984
2
    fn test_message_add_bytes_command_1() {
985
2
        // build a command message with word count 1
986
2
        let mut message = Message::<2>::new().with_command(0b0000000000000001);
987
2

            
988
2
        message.add_bytes(&[1, 2]);
989
2
        message.add_bytes(&[3, 4]);
990
2

            
991
2
        // failed because the message only has enough space
992
2
        // for two characters (one data word), but two were given.
993
2
        assert!(!message.is_valid());
994

            
995
2
        assert!(message.is_full());
996
2
        assert_eq!(message.length(), 2);
997
2
        assert_eq!(message.count(), 1);
998
2
        assert_eq!(message.size(), 2);
999
2
        assert!(message.is_command());
2
        assert!(!message.is_status());
2
    }
    #[test]
2
    fn test_message_add_bytes_command_2() {
2
        // build a command message with word count 1
2
        let mut message = Message::<2>::new().with_command(0b0000000000000001);
2

            
2
        message.add_bytes(&[1, 2, 3, 4]);
2

            
2
        // failed because the given string is too long
2
        // to fit in a message with size 2
2
        assert!(!message.is_valid());
2
        assert_eq!(message.length(), 2);
2
        assert_eq!(message.count(), 1);
2
        assert_eq!(message.size(), 2);
2
        assert!(message.is_command());
2
        assert!(!message.is_status());
2
    }
    #[test]
2
    fn test_message_add_bytes_command_3() {
2
        // build a command message with word count 2
2
        let mut message = Message::<3>::new().with_command(0b0000000000000010);
2

            
2
        message.add_bytes(&[1, 2, 3, 4]);
2

            
2
        assert!(message.is_valid());
2
        assert_eq!(message.length(), 3);
2
        assert_eq!(message.count(), 2);
2
        assert_eq!(message.size(), 3);
2
        assert!(message.is_command());
2
        assert!(!message.is_status());
2
    }
    #[test]
2
    fn test_message_with_bad_count_fail() {
2
        // adding two header words to the message
2
        let message = Message::<2>::new()
2
            .with_command(0b0000000000000001)
2
            .with_data(0b0000000000000000)
2
            .with_data(0b0000000000000000);
2
        assert!(message.error.is_some());
2
        assert!(!message.is_valid());
2
    }
    #[test]
2
    fn test_message_default() {
2
        let message: Message = Message::default();
2
        assert_eq!(message.length(), 0);
2
        assert_eq!(message.count(), 0);
2
        assert_eq!(message.size(), 33);
2
    }
    #[test]
2
    fn test_message_clone() {
2
        let message1 = Message::<2>::new()
2
            .with_command(0b0000000000000001)
2
            .with_data(0b0000000000000001)
2
            .build()
2
            .unwrap();
2

            
2
        let message2 = message1.clone();
2
        assert_eq!(message1, message2);
2
    }
    #[test]
2
    fn test_message_new() {
2
        let message: Message = Message::new();
2
        assert_eq!(message.length(), 0);
2
        assert_eq!(message.count(), 0);
2
        assert_eq!(message.size(), 33);
2
    }
    #[test]
2
    fn test_message_with_command() {
2
        let message = Message::<2>::new()
2
            .with_command(0b0000000000000001)
2
            .with_data(0b0000000000000001)
2
            .build()
2
            .unwrap();
2
        assert!(message.is_full());
2
        assert_eq!(message.length(), 2);
2
        assert_eq!(message.count(), 1);
2
        assert_eq!(message.size(), 2);
2
        assert_eq!(message.limit(), 1);
2
        assert!(message.is_command());
2
        assert!(!message.is_status());
2
    }
    #[test]
2
    fn test_message_with_command_fail_duplicate_header() {
2
        // adding two header words to the message
2
        let message = Message::<2>::new()
2
            .with_command(0b0000000000000001)
2
            .with_command(0b0000000000000001)
2
            .build();
2
        assert!(message.is_err());
2
    }
    #[test]
2
    fn test_message_with_command_fail_header_not_first() {
2
        // add a data word to the message first
2
        let message = Message::<2>::new()
2
            .with_data(0b0000000000000001)
2
            .with_command(0b0000000000000001)
2
            .build();
2
        assert!(message.is_err());
2
    }
    #[test]
2
    fn test_message_with_command_fail_message_full() {
2
        let result = Message::<0>::new().with_command(0b0000000000000001).build();
2
        assert!(result.is_err());
2
    }
    #[test]
2
    fn test_message_add_command_fail_parity() {
2
        let word = CommandWord::new()
2
            .with_value(0b0000000000000000)
2
            .with_parity(0);
2

            
2
        let result = Message::<1>::new().with_command(word).build();
2

            
2
        assert_eq!(result, Err(Error::InvalidWord));
2
    }
    #[test]
2
    fn test_message_with_status() {
2
        let message = Message::<2>::new()
2
            .with_status(0b0000000000000001)
2
            .with_data(0b0000000000000001)
2
            .build()
2
            .unwrap();
2
        assert!(message.is_valid());
2
        assert!(message.is_full());
2
        assert_eq!(message.length(), 2);
2
        assert_eq!(message.count(), 1);
2
        assert_eq!(message.size(), 2);
2
        assert_eq!(message.limit(), 1);
2
        assert!(message.is_status());
2
        assert!(!message.is_command());
2
    }
    #[test]
2
    fn test_message_with_status_fail_duplicate_header() {
2
        // adding two header words to the message
2
        let message = Message::<2>::new()
2
            .with_status(0b0000000000000001)
2
            .with_status(0b0000000000000001)
2
            .build();
2
        assert!(message.is_err());
2
    }
    #[test]
2
    fn test_message_with_status_fail_header_not_first() {
2
        // add a data word to the message first
2
        let message = Message::<2>::new()
2
            .with_data(0b0000000000000001)
2
            .with_status(0b0000000000000001)
2
            .build();
2
        assert!(message.is_err());
2
    }
    #[test]
2
    fn test_message_with_status_fail_message_full() {
2
        let result = Message::<0>::new().with_status(0b0000000000000001).build();
2
        assert!(result.is_err());
2
    }
    #[test]
2
    fn test_message_add_status_fail_parity() {
2
        let word = StatusWord::new()
2
            .with_value(0b0000000000000000)
2
            .with_parity(0);
2

            
2
        let result = Message::<1>::new().with_status(word).build();
2

            
2
        assert_eq!(result, Err(Error::InvalidWord));
2
    }
    #[test]
2
    fn test_message_with_data() {
2
        let message = Message::<2>::new()
2
            .with_status(0b0000000000000001)
2
            .with_data(0b0000000000000001)
2
            .build()
2
            .unwrap();
2
        assert_eq!(message.length(), 2);
2
        assert_eq!(message.count(), 1);
2
        assert_eq!(message.size(), 2);
2
    }
    #[test]
2
    fn test_message_with_data_fail() {
2
        let result = Message::<2>::new().with_data(0b0000000000000001).build();
2
        assert!(result.is_err());
2
    }
    #[test]
2
    fn test_message_with_data_fail_message_full() {
2
        let result = Message::<2>::new()
2
            .with_status(0b0000000000000001)
2
            .with_data(0b0000000000000001)
2
            .with_data(0b0000000000000001)
2
            .build();
2
        assert!(result.is_err());
2
    }
    #[test]
2
    fn test_message_with_word_command() {
2
        let message = Message::<2>::new()
2
            .with_word(CommandWord::from(0b0000000000000001))
2
            .with_word(DataWord::from(0b0000000000000001))
2
            .build()
2
            .unwrap();
2
        assert_eq!(message.length(), 2);
2
        assert_eq!(message.count(), 1);
2
        assert_eq!(message.size(), 2);
2
    }
    #[test]
2
    fn test_message_with_word_status() {
2
        let message = Message::<2>::new()
2
            .with_word(StatusWord::from(0b0000000000000001))
2
            .with_word(DataWord::from(0b0000000000000001))
2
            .build()
2
            .unwrap();
2
        assert_eq!(message.length(), 2);
2
        assert_eq!(message.count(), 1);
2
        assert_eq!(message.size(), 2);
2
    }
    #[test]
2
    fn test_message_read_write_command_0() {
2
        let input = [0b10000011, 0b00001100, 0b00100010, 0b11010000, 0b11010010];
2
        let length = 2;
2

            
2
        let l = input.len();
2
        let mut buffer = [0; 10];
2

            
2
        let message = Message::<4>::read_command(&input).unwrap();
2
        message.write(&mut buffer).unwrap();
2

            
2
        assert_eq!(&buffer[..l], input);
2
        assert_eq!(message.length(), length);
2
    }
    #[test]
2
    fn test_message_read_write_command_1() {
2
        let input = [
2
            0b10000011, 0b00001100, 0b01110010, 0b11010000, 0b11010010, 0b00101111, 0b00101101,
2
            0b11100010, 0b11001110, 0b11011110,
2
        ];
2
        let length = 4;
2

            
2
        let l = input.len();
2
        let mut buffer = [0; 10];
2

            
2
        let message = Message::<4>::read_command(&input).unwrap();
2
        message.write(&mut buffer).unwrap();
2

            
2
        assert_eq!(&buffer[..l], input);
2
        assert_eq!(message.length(), length);
2
    }
    #[test]
2
    fn test_message_read_write_status_0() {
2
        let input = [0b10000011, 0b00001100, 0b00100010, 0b11010000, 0b11010010];
2
        let length = 2;
2

            
2
        let l = input.len();
2
        let mut buffer = [0; 10];
2

            
2
        let message = Message::<4>::read_status(&input).unwrap();
2
        message.write(&mut buffer).unwrap();
2

            
2
        assert_eq!(&buffer[..l], input);
2
        assert_eq!(message.length(), length);
2
    }
    #[test]
2
    fn test_message_read_write_status_1() {
2
        let input = [
2
            0b10000011, 0b00001100, 0b01110010, 0b11010000, 0b11010010, 0b00101111, 0b00101101,
2
            0b11100010, 0b11001110, 0b11011110,
2
        ];
2
        let length = 4;
2

            
2
        let l = input.len();
2
        let mut buffer = [0; 10];
2

            
2
        let message = Message::<4>::read_status(&input).unwrap();
2
        message.write(&mut buffer).unwrap();
2

            
2
        assert_eq!(&buffer[..l], input);
2
        assert_eq!(message.length(), length);
2
    }
    #[test]
2
    fn test_message_read_status_no_data() {
2
        let input = [0b10000011, 0b00001100, 0b00100010];
2
        let message = Message::<1>::read_status(&input).unwrap();
2
        assert_eq!(message.length(), 1);
2
    }
    #[test]
2
    fn test_message_read_status_fail_buffer_too_small() {
2
        let input = [0b10000011, 0b00001100];
2
        let result = Message::<1>::read_status(&input);
2
        assert_eq!(result, Err(Error::InvalidMessage));
2
    }
    #[test]
2
    fn test_message_read_command_fail_buffer_too_small() {
2
        let input = [0b10000011, 0b00001100, 0b00100010];
2
        let result = Message::<2>::read_command(&input);
2
        assert_eq!(result, Err(Error::InvalidMessage));
2
    }
    #[test]
2
    fn test_message_write_command_fail_buffer_too_small() {
2
        let mut buffer = [0, 0, 0];
2

            
2
        let message = Message::<2>::new()
2
            .with_command(0b0001100001100001)
2
            .with_data(0b0000000000000000)
2
            .build()
2
            .unwrap();
2

            
2
        let result = message.write(&mut buffer);
2
        assert_eq!(result, Err(Error::OutOfBounds));
2
    }
    #[test]
2
    fn test_message_write_status_fail_buffer_too_small() {
2
        let mut buffer = [0, 0, 0];
2

            
2
        let message = Message::<2>::new()
2
            .with_status(0b0001100001100001)
2
            .with_data(0b0000000000000000)
2
            .build()
2
            .unwrap();
2

            
2
        let result = message.write(&mut buffer);
2
        assert_eq!(result, Err(Error::OutOfBounds));
2
    }
    #[test]
2
    fn test_message_status() {
2
        let message = Message::<1>::new()
2
            .with_status(0b0000000000000001)
2
            .build()
2
            .unwrap();
2
        assert!(message.status().is_some());
2
    }
    #[test]
2
    fn test_message_command() {
2
        let message = Message::<2>::new()
2
            .with_command(0b0000000000000001)
2
            .with_data(0b0000000000000000)
2
            .build()
2
            .unwrap();
2
        assert!(message.command().is_some());
2
    }
    #[test]
2
    fn test_message_at() {
2
        let data1: DataWord = 0b0000000000000101.into();
2
        let data2: DataWord = 0b0000000000010101.into();
2
        let data3: DataWord = 0b0000000001010101.into();
2

            
2
        let message = Message::<4>::new()
2
            .with_command(0b0000000000000011)
2
            .with_data(data1)
2
            .with_data(data2)
2
            .with_data(data3)
2
            .build()
2
            .unwrap();
2

            
2
        let word1 = message.at(0);
2
        let word2 = message.at(1);
2
        let word3 = message.at(2);
2
        let word4 = message.at(3);
2

            
2
        assert_eq!(word1, Some(&data1));
2
        assert_eq!(word2, Some(&data2));
2
        assert_eq!(word3, Some(&data3));
2
        assert_eq!(word4, None);
2
    }
    #[test]
2
    fn test_message_get() {
2
        let data1: u16 = 0b0000000000000101;
2
        let data2: u16 = 0b0000000000010101;
2
        let data3: u16 = 0b0000000001010101;
2

            
2
        let message = Message::<4>::new()
2
            .with_command(0b0000000000000011)
2
            .with_data(data1)
2
            .with_data(data2)
2
            .with_data(data3)
2
            .build()
2
            .unwrap();
2

            
2
        let word1 = message.get::<u16>(0);
2
        let word2 = message.get::<u16>(1);
2
        let word3 = message.get::<u16>(2);
2
        let word4 = message.get::<u16>(3);
2

            
2
        assert_eq!(word1, Some(data1));
2
        assert_eq!(word2, Some(data2));
2
        assert_eq!(word3, Some(data3));
2
        assert_eq!(word4, None);
2
    }
    #[test]
2
    fn test_message_clear() {
2
        let mut message = Message::<2>::new()
2
            .with_command(0b0000000000000001)
2
            .with_data(0b0000000000000001)
2
            .build()
2
            .unwrap();
2

            
2
        message.clear();
2

            
2
        assert_eq!(message.length(), 0);
2
        assert_eq!(message.count(), 0);
2
        assert_eq!(message.size(), 2);
2
        assert!(message.is_empty());
2
        assert!(!message.is_full());
2
    }
}