resol_vbus/
data.rs

1use std::{
2    cmp::Ordering::{self, Equal, Greater, Less},
3    hash::Hasher,
4};
5
6use crate::{
7    datagram::Datagram, header::Header, id_hash::IdHash, packet::Packet, telegram::Telegram,
8};
9
10/// `Data` is a type that contains one of the supported VBus protocol data variants.
11///
12/// # Examples
13///
14/// ```rust
15/// use std::io::Read;
16///
17/// use resol_vbus::{LiveDataReader, Result};
18///
19/// # #[allow(dead_code)]
20/// fn print_data_ids<R: Read>(r: R) -> Result<()> {
21///     let mut ldr = LiveDataReader::new(0, r);
22///
23///     while let Some(data) = ldr.read_data()? {
24///         if !data.is_packet() {
25///             continue;
26///         }
27///
28///         println!("{}: {}", data.as_header().timestamp, data.id_string());
29///     }
30///
31///     Ok(())
32/// }
33/// ```
34#[derive(Clone, Debug)]
35pub enum Data {
36    /// Contains a `Packet` conforming to VBus protocol version 1.x.
37    Packet(Packet),
38
39    /// Contains a `Datagram` conforming to VBus protocol version 2.x.
40    Datagram(Datagram),
41
42    /// Contains a `Telegram` conforming to VBus protocol version 3.x.
43    Telegram(Telegram),
44}
45
46impl Data {
47    /// Returns `true` if the variant is a `Packet`.
48    pub fn is_packet(&self) -> bool {
49        matches!(*self, Data::Packet(_))
50    }
51
52    /// Returns `true` if the variant is a `Packet`.
53    pub fn is_datagram(&self) -> bool {
54        matches!(*self, Data::Datagram(_))
55    }
56
57    /// Returns `true` if the variant is a `Packet`.
58    pub fn is_telegram(&self) -> bool {
59        matches!(*self, Data::Telegram(_))
60    }
61
62    /// Returns the `Packet` value, consuming the `Data` value.
63    ///
64    /// # Panics
65    ///
66    /// The function panics if the `Data` value is no `Packet` variant.
67    pub fn into_packet(self) -> Packet {
68        match self {
69            Data::Packet(packet) => packet,
70            _ => panic!(
71                "called `Data::into_packet` for a non-`Packet` value: {:?}",
72                self
73            ),
74        }
75    }
76
77    /// Returns the `Datagram` value, consuming the `Data` value.
78    ///
79    /// # Panics
80    ///
81    /// The function panics if the `Data` value is no `Datagram` variant.
82    pub fn into_datagram(self) -> Datagram {
83        match self {
84            Data::Datagram(datagram) => datagram,
85            _ => panic!(
86                "called `Data::into_datagram` for a non-`Datagram` value: {:?}",
87                self
88            ),
89        }
90    }
91
92    /// Returns the `Telegram` value, consuming the `Data` value.
93    ///
94    /// # Panics
95    ///
96    /// The function panics if the `Data` value is no `Telegram` variant.
97    pub fn into_telegram(self) -> Telegram {
98        match self {
99            Data::Telegram(telegram) => telegram,
100            _ => panic!(
101                "called `Data::into_telegram` for a non-`Telegram` value: {:?}",
102                self
103            ),
104        }
105    }
106
107    /// Returns the `Header` part of the variant inside this `Data`.
108    pub fn as_header(&self) -> &Header {
109        self.as_ref()
110    }
111
112    /// Returns the `Packet` value.
113    ///
114    /// # Panics
115    ///
116    /// The function panics if the `Data` value is no `Packet` variant.
117    pub fn as_packet(&self) -> &Packet {
118        match *self {
119            Data::Packet(ref packet) => packet,
120            _ => panic!(
121                "called `Data::as_packet` for a non-`Packet` value: {:?}",
122                self
123            ),
124        }
125    }
126
127    /// Returns the `Datagram` value.
128    ///
129    /// # Panics
130    ///
131    /// The function panics if the `Data` value is no `Datagram` variant.
132    pub fn as_datagram(&self) -> &Datagram {
133        match *self {
134            Data::Datagram(ref datagram) => datagram,
135            _ => panic!(
136                "called `Data::as_datagram` for a non-`Datagram` value: {:?}",
137                self
138            ),
139        }
140    }
141
142    /// Returns the `Telegram` value.
143    ///
144    /// # Panics
145    ///
146    /// The function panics if the `Data` value is no `Telegram` variant.
147    pub fn as_telegram(&self) -> &Telegram {
148        match *self {
149            Data::Telegram(ref telegram) => telegram,
150            _ => panic!(
151                "called `Data::as_telegram` for a non-`Telegram` value: {:?}",
152                self
153            ),
154        }
155    }
156
157    /// Creates an identification string for the variant inside this `Data`.
158    pub fn id_string(&self) -> String {
159        match *self {
160            Data::Packet(ref packet) => packet.id_string(),
161            Data::Datagram(ref dgram) => dgram.id_string(),
162            Data::Telegram(ref tgram) => tgram.id_string(),
163        }
164    }
165}
166
167impl IdHash for Data {
168    fn id_hash<H: Hasher>(&self, h: &mut H) {
169        match *self {
170            Data::Packet(ref packet) => packet.id_hash(h),
171            Data::Datagram(ref dgram) => dgram.id_hash(h),
172            Data::Telegram(ref tgram) => tgram.id_hash(h),
173        }
174    }
175}
176
177impl PartialEq for Data {
178    /// Returns `true` if two `Data` values are "identical".
179    ///
180    /// Each `Data` variant has a set of fields that make up its "identity". The `PartialEq` trait
181    /// implementation checks those fields for equality and returns `true` if all of the fields
182    /// match.
183    ///
184    /// See the descriptions for the `Header`, `Packet`, `Datagram` and `Telegram` types to find
185    /// out which fields are considered in each case.
186    fn eq(&self, right: &Data) -> bool {
187        let left = self;
188
189        let left_header = left.as_header();
190        let right_header = right.as_header();
191
192        if left_header.channel != right_header.channel {
193            false
194        } else if left_header.destination_address != right_header.destination_address {
195            false
196        } else if left_header.source_address != right_header.source_address {
197            false
198        } else if left_header.protocol_version != right_header.protocol_version {
199            false
200        } else {
201            match *left {
202                Data::Packet(ref left_packet) => {
203                    if let Data::Packet(ref right_packet) = *right {
204                        if left_packet.command != right_packet.command {
205                            false
206                        } else {
207                            true
208                        }
209                    } else {
210                        false
211                    }
212                }
213                Data::Datagram(ref left_dgram) => {
214                    if let Data::Datagram(ref right_dgram) = *right {
215                        if left_dgram.command != right_dgram.command {
216                            false
217                        } else if left_dgram.command != 0x0900 {
218                            true
219                        } else if left_dgram.param16 != right_dgram.param16 {
220                            false
221                        } else {
222                            true
223                        }
224                    } else {
225                        false
226                    }
227                }
228                Data::Telegram(ref left_tgram) => {
229                    if let Data::Telegram(ref right_tgram) = *right {
230                        if left_tgram.command != right_tgram.command {
231                            false
232                        } else {
233                            true
234                        }
235                    } else {
236                        false
237                    }
238                }
239            }
240        }
241    }
242}
243
244impl PartialOrd for Data {
245    /// Compares two `Data` values are "identical".
246    ///
247    /// Each `Data` variant has a set of fields that make up its "identity". The `PartialOrd` trait
248    /// implementation compares those fields.
249    ///
250    /// See the descriptions for the `Header`, `Packet`, `Datagram` and `Telegram` types to find
251    /// out which fields are considered in each case.
252    fn partial_cmp(&self, right: &Data) -> Option<Ordering> {
253        let left = self;
254
255        let left_header = left.as_header();
256        let right_header = right.as_header();
257
258        if left_header.channel < right_header.channel {
259            Some(Less)
260        } else if left_header.channel > right_header.channel {
261            Some(Greater)
262        } else if left_header.destination_address < right_header.destination_address {
263            Some(Less)
264        } else if left_header.destination_address > right_header.destination_address {
265            Some(Greater)
266        } else if left_header.source_address < right_header.source_address {
267            Some(Less)
268        } else if left_header.source_address > right_header.source_address {
269            Some(Greater)
270        } else if left_header.protocol_version < right_header.protocol_version {
271            Some(Less)
272        } else if left_header.protocol_version > right_header.protocol_version {
273            Some(Greater)
274        } else {
275            match *left {
276                Data::Packet(ref left_packet) => {
277                    if let Data::Packet(ref right_packet) = *right {
278                        Some(left_packet.command.cmp(&right_packet.command))
279                    } else {
280                        None
281                    }
282                }
283                Data::Datagram(ref left_dgram) => {
284                    if let Data::Datagram(ref right_dgram) = *right {
285                        if left_dgram.command < right_dgram.command {
286                            Some(Less)
287                        } else if left_dgram.command > right_dgram.command {
288                            Some(Greater)
289                        } else if left_dgram.command != 0x0900 {
290                            Some(Equal)
291                        } else if left_dgram.param16 < right_dgram.param16 {
292                            Some(Less)
293                        } else if left_dgram.param16 > right_dgram.param16 {
294                            Some(Greater)
295                        } else {
296                            Some(Equal)
297                        }
298                    } else {
299                        None
300                    }
301                }
302                Data::Telegram(ref left_tgram) => {
303                    if let Data::Telegram(ref right_tgram) = *right {
304                        Some(left_tgram.command.cmp(&right_tgram.command))
305                    } else {
306                        None
307                    }
308                }
309            }
310        }
311    }
312}
313
314impl From<Packet> for Data {
315    fn from(packet: Packet) -> Data {
316        Data::Packet(packet)
317    }
318}
319
320impl From<Datagram> for Data {
321    fn from(dgram: Datagram) -> Data {
322        Data::Datagram(dgram)
323    }
324}
325
326impl From<Telegram> for Data {
327    fn from(tgram: Telegram) -> Data {
328        Data::Telegram(tgram)
329    }
330}
331
332impl AsRef<Header> for Data {
333    fn as_ref(&self) -> &Header {
334        match *self {
335            Data::Packet(ref packet) => packet.as_ref(),
336            Data::Datagram(ref dgram) => dgram.as_ref(),
337            Data::Telegram(ref tgram) => tgram.as_ref(),
338        }
339    }
340}
341
342#[cfg(test)]
343mod tests {
344    use super::*;
345
346    use chrono::{DateTime, TimeZone, Utc};
347
348    use crate::{
349        id_hash::id_hash,
350        live_data_decoder::data_from_checked_bytes,
351        test_data::{LIVE_DATA_1, LIVE_TELEGRAM_1},
352    };
353
354    fn packet_data(timestamp: DateTime<Utc>, channel: u8) -> Data {
355        data_from_checked_bytes(timestamp, channel, &LIVE_DATA_1[0..])
356    }
357
358    fn datagram_data(timestamp: DateTime<Utc>, channel: u8) -> Data {
359        data_from_checked_bytes(timestamp, channel, &LIVE_DATA_1[352..])
360    }
361
362    fn telegram_data(timestamp: DateTime<Utc>, channel: u8) -> Data {
363        data_from_checked_bytes(timestamp, channel, &LIVE_TELEGRAM_1[0..])
364    }
365
366    #[test]
367    fn test_is_packet() {
368        let timestamp = Utc.timestamp(1485688933, 0);
369        let channel = 0x11;
370
371        let packet_data = packet_data(timestamp, channel);
372        assert_eq!(true, packet_data.is_packet());
373
374        let dgram_data = datagram_data(timestamp, channel);
375        assert_eq!(false, dgram_data.is_packet());
376
377        let tgram_data = telegram_data(timestamp, channel);
378        assert_eq!(false, tgram_data.is_packet());
379    }
380
381    #[test]
382    fn test_is_datagram() {
383        let timestamp = Utc.timestamp(1485688933, 0);
384        let channel = 0x11;
385
386        let packet_data = packet_data(timestamp, channel);
387        assert_eq!(false, packet_data.is_datagram());
388
389        let dgram_data = datagram_data(timestamp, channel);
390        assert_eq!(true, dgram_data.is_datagram());
391
392        let tgram_data = telegram_data(timestamp, channel);
393        assert_eq!(false, tgram_data.is_datagram());
394    }
395
396    #[test]
397    fn test_is_telegram() {
398        let timestamp = Utc.timestamp(1485688933, 0);
399        let channel = 0x11;
400
401        let packet_data = packet_data(timestamp, channel);
402        assert_eq!(false, packet_data.is_telegram());
403
404        let dgram_data = datagram_data(timestamp, channel);
405        assert_eq!(false, dgram_data.is_telegram());
406
407        let tgram_data = telegram_data(timestamp, channel);
408        assert_eq!(true, tgram_data.is_telegram());
409    }
410
411    #[test]
412    fn test_into_packet() {
413        let timestamp = Utc.timestamp(1485688933, 0);
414        let channel = 0x11;
415
416        let packet_data = packet_data(timestamp, channel);
417        let packet = packet_data.into_packet();
418
419        assert_eq!(timestamp, packet.header.timestamp);
420        assert_eq!(channel, packet.header.channel);
421        assert_eq!(0x0010, packet.header.destination_address);
422        assert_eq!(0x7E11, packet.header.source_address);
423        assert_eq!(0x10, packet.header.protocol_version);
424    }
425
426    #[test]
427    #[should_panic]
428    fn test_into_packet_panic() {
429        let timestamp = Utc.timestamp(1485688933, 0);
430        let channel = 0x11;
431
432        let dgram_data = datagram_data(timestamp, channel);
433        dgram_data.into_packet();
434    }
435
436    #[test]
437    fn test_into_datagram() {
438        let timestamp = Utc.timestamp(1485688933, 0);
439        let channel = 0x11;
440
441        let dgram_data = datagram_data(timestamp, channel);
442        let dgram = dgram_data.into_datagram();
443
444        assert_eq!(timestamp, dgram.header.timestamp);
445        assert_eq!(channel, dgram.header.channel);
446        assert_eq!(0x0000, dgram.header.destination_address);
447        assert_eq!(0x7E11, dgram.header.source_address);
448        assert_eq!(0x20, dgram.header.protocol_version);
449    }
450
451    #[test]
452    #[should_panic]
453    fn test_into_datagram_panic() {
454        let timestamp = Utc.timestamp(1485688933, 0);
455        let channel = 0x11;
456
457        let tgram_data = telegram_data(timestamp, channel);
458        tgram_data.into_datagram();
459    }
460
461    #[test]
462    fn test_into_telegram() {
463        let timestamp = Utc.timestamp(1485688933, 0);
464        let channel = 0x11;
465
466        let tgram_data = telegram_data(timestamp, channel);
467        let tgram = tgram_data.into_telegram();
468
469        assert_eq!(timestamp, tgram.header.timestamp);
470        assert_eq!(channel, tgram.header.channel);
471        assert_eq!(0x7771, tgram.header.destination_address);
472        assert_eq!(0x2011, tgram.header.source_address);
473        assert_eq!(0x30, tgram.header.protocol_version);
474    }
475
476    #[test]
477    #[should_panic]
478    fn test_into_telegram_panic() {
479        let timestamp = Utc.timestamp(1485688933, 0);
480        let channel = 0x11;
481
482        let packet_data = packet_data(timestamp, channel);
483        packet_data.into_telegram();
484    }
485
486    #[test]
487    fn test_as_header() {
488        let timestamp = Utc.timestamp(1485688933, 0);
489        let channel = 0x11;
490
491        let packet_data = packet_data(timestamp, channel);
492
493        let header = packet_data.as_header();
494        assert_eq!(timestamp, header.timestamp);
495        assert_eq!(channel, header.channel);
496        assert_eq!(0x0010, header.destination_address);
497        assert_eq!(0x7E11, header.source_address);
498        assert_eq!(0x10, header.protocol_version);
499
500        let dgram_data = datagram_data(timestamp, channel);
501
502        let header = dgram_data.as_header();
503        assert_eq!(timestamp, header.timestamp);
504        assert_eq!(channel, header.channel);
505        assert_eq!(0x0000, header.destination_address);
506        assert_eq!(0x7E11, header.source_address);
507        assert_eq!(0x20, header.protocol_version);
508
509        let tgram_data = telegram_data(timestamp, channel);
510
511        let header = tgram_data.as_header();
512        assert_eq!(timestamp, header.timestamp);
513        assert_eq!(channel, header.channel);
514        assert_eq!(0x7771, header.destination_address);
515        assert_eq!(0x2011, header.source_address);
516        assert_eq!(0x30, header.protocol_version);
517    }
518
519    #[test]
520    fn test_as_packet() {
521        let timestamp = Utc.timestamp(1485688933, 0);
522        let channel = 0x11;
523
524        let packet_data = packet_data(timestamp, channel);
525        packet_data.as_packet();
526    }
527
528    #[test]
529    #[should_panic]
530    fn test_as_packet_panic() {
531        let timestamp = Utc.timestamp(1485688933, 0);
532        let channel = 0x11;
533
534        let datagram_data = datagram_data(timestamp, channel);
535        datagram_data.as_packet();
536    }
537
538    #[test]
539    fn test_as_datagram() {
540        let timestamp = Utc.timestamp(1485688933, 0);
541        let channel = 0x11;
542
543        let datagram_data = datagram_data(timestamp, channel);
544        datagram_data.as_datagram();
545    }
546
547    #[test]
548    #[should_panic]
549    fn test_as_datagram_panic() {
550        let timestamp = Utc.timestamp(1485688933, 0);
551        let channel = 0x11;
552
553        let telegram_data = telegram_data(timestamp, channel);
554        telegram_data.as_datagram();
555    }
556
557    #[test]
558    fn test_as_telegram() {
559        let timestamp = Utc.timestamp(1485688933, 0);
560        let channel = 0x11;
561
562        let telegram_data = telegram_data(timestamp, channel);
563        telegram_data.as_telegram();
564    }
565
566    #[test]
567    #[should_panic]
568    fn test_as_telegram_panic() {
569        let timestamp = Utc.timestamp(1485688933, 0);
570        let channel = 0x11;
571
572        let packet_data = packet_data(timestamp, channel);
573        packet_data.as_telegram();
574    }
575
576    #[test]
577    fn test_eq() {
578        let timestamp = Utc.timestamp(1485688933, 0);
579        let channel = 0x11;
580
581        let packet_data = packet_data(timestamp, channel);
582        let packet = packet_data.clone().into_packet();
583
584        let dgram_data = datagram_data(timestamp, channel);
585        let dgram = dgram_data.clone().into_datagram();
586
587        let tgram_data = telegram_data(timestamp, channel);
588        let tgram = tgram_data.clone().into_telegram();
589
590        let other_timestamp = Utc.timestamp(0, 0);
591
592        // Between variants
593        assert_eq!(false, packet_data.eq(&dgram_data));
594        assert_eq!(false, packet_data.eq(&tgram_data));
595        assert_eq!(false, dgram_data.eq(&tgram_data));
596
597        // ---- Packet ----
598        let other = packet.clone();
599        assert_eq!(true, Data::Packet(other).eq(&packet_data));
600
601        let mut other = packet.clone();
602        other.header.timestamp = other_timestamp;
603        assert_eq!(true, Data::Packet(other).eq(&packet_data));
604
605        let mut other = packet.clone();
606        other.header.channel ^= 1;
607        assert_eq!(false, Data::Packet(other).eq(&packet_data));
608
609        let mut other = packet.clone();
610        other.header.destination_address ^= 1;
611        assert_eq!(false, Data::Packet(other).eq(&packet_data));
612
613        let mut other = packet.clone();
614        other.header.source_address ^= 1;
615        assert_eq!(false, Data::Packet(other).eq(&packet_data));
616
617        let mut other = packet.clone();
618        other.header.protocol_version ^= 1;
619        assert_eq!(false, Data::Packet(other).eq(&packet_data));
620
621        let mut other = packet.clone();
622        other.command ^= 1;
623        assert_eq!(false, Data::Packet(other).eq(&packet_data));
624
625        let mut other = packet.clone();
626        other.frame_count ^= 1;
627        assert_eq!(true, Data::Packet(other).eq(&packet_data));
628
629        let mut other = packet.clone();
630        other.frame_data[0] ^= 1;
631        assert_eq!(true, Data::Packet(other).eq(&packet_data));
632
633        // ---- Datagram ----
634        let other = dgram.clone();
635        assert_eq!(true, Data::Datagram(other).eq(&dgram_data));
636
637        let mut other = dgram.clone();
638        other.header.timestamp = other_timestamp;
639        assert_eq!(true, Data::Datagram(other).eq(&dgram_data));
640
641        let mut other = dgram.clone();
642        other.header.channel ^= 1;
643        assert_eq!(false, Data::Datagram(other).eq(&dgram_data));
644
645        let mut other = dgram.clone();
646        other.header.destination_address ^= 1;
647        assert_eq!(false, Data::Datagram(other).eq(&dgram_data));
648
649        let mut other = dgram.clone();
650        other.header.source_address ^= 1;
651        assert_eq!(false, Data::Datagram(other).eq(&dgram_data));
652
653        let mut other = dgram.clone();
654        other.header.protocol_version ^= 1;
655        assert_eq!(false, Data::Datagram(other).eq(&dgram_data));
656
657        let mut other = dgram.clone();
658        other.command ^= 1;
659        assert_eq!(false, Data::Datagram(other).eq(&dgram_data));
660
661        let mut other = dgram.clone();
662        other.param16 ^= 1;
663        assert_eq!(true, Data::Datagram(other).eq(&dgram_data));
664
665        let mut other = dgram.clone();
666        other.param32 ^= 1;
667        assert_eq!(true, Data::Datagram(other).eq(&dgram_data));
668
669        // ---- Telegram ----
670        let other = tgram.clone();
671        assert_eq!(true, Data::Telegram(other).eq(&tgram_data));
672
673        let mut other = tgram.clone();
674        other.header.timestamp = other_timestamp;
675        assert_eq!(true, Data::Telegram(other).eq(&tgram_data));
676
677        let mut other = tgram.clone();
678        other.header.channel ^= 1;
679        assert_eq!(false, Data::Telegram(other).eq(&tgram_data));
680
681        let mut other = tgram.clone();
682        other.header.destination_address ^= 1;
683        assert_eq!(false, Data::Telegram(other).eq(&tgram_data));
684
685        let mut other = tgram.clone();
686        other.header.source_address ^= 1;
687        assert_eq!(false, Data::Telegram(other).eq(&tgram_data));
688
689        let mut other = tgram.clone();
690        other.header.protocol_version ^= 1;
691        assert_eq!(false, Data::Telegram(other).eq(&tgram_data));
692
693        let mut other = tgram.clone();
694        other.command ^= 1;
695        assert_eq!(false, Data::Telegram(other).eq(&tgram_data));
696
697        let mut other = tgram.clone();
698        other.frame_data[0] ^= 1;
699        assert_eq!(true, Data::Telegram(other).eq(&tgram_data));
700    }
701
702    #[test]
703    fn test_partial_cmp() {
704        let timestamp = Utc.timestamp(1485688933, 0);
705        let channel = 0x11;
706
707        let packet_data = packet_data(timestamp, channel);
708        let packet = match packet_data {
709            Data::Packet(ref packet) => packet,
710            _ => unreachable!(),
711        };
712
713        let dgram_data = datagram_data(timestamp, channel);
714        let dgram = match dgram_data {
715            Data::Datagram(ref dgram) => dgram,
716            _ => unreachable!(),
717        };
718
719        let tgram_data = telegram_data(timestamp, channel);
720        let tgram = match tgram_data {
721            Data::Telegram(ref tgram) => tgram,
722            _ => unreachable!(),
723        };
724
725        let other_timestamp = Utc.timestamp(0, 0);
726
727        // Between variants
728        assert_eq!(Some(Greater), packet_data.partial_cmp(&dgram_data));
729        assert_eq!(Some(Less), packet_data.partial_cmp(&tgram_data));
730        assert_eq!(Some(Less), dgram_data.partial_cmp(&tgram_data));
731
732        // ---- Packet ----
733        let other = packet.clone();
734        assert_eq!(Some(Equal), Data::Packet(other).partial_cmp(&packet_data));
735
736        let mut other = packet.clone();
737        other.header.timestamp = other_timestamp;
738        assert_eq!(Some(Equal), Data::Packet(other).partial_cmp(&packet_data));
739
740        let mut other = packet.clone();
741        other.header.channel -= 1;
742        assert_eq!(Some(Less), Data::Packet(other).partial_cmp(&packet_data));
743
744        let mut other = packet.clone();
745        other.header.channel += 1;
746        assert_eq!(Some(Greater), Data::Packet(other).partial_cmp(&packet_data));
747
748        let mut other = packet.clone();
749        other.header.destination_address -= 1;
750        assert_eq!(Some(Less), Data::Packet(other).partial_cmp(&packet_data));
751
752        let mut other = packet.clone();
753        other.header.destination_address += 1;
754        assert_eq!(Some(Greater), Data::Packet(other).partial_cmp(&packet_data));
755
756        let mut other = packet.clone();
757        other.header.source_address -= 1;
758        assert_eq!(Some(Less), Data::Packet(other).partial_cmp(&packet_data));
759
760        let mut other = packet.clone();
761        other.header.source_address += 1;
762        assert_eq!(Some(Greater), Data::Packet(other).partial_cmp(&packet_data));
763
764        let mut other = packet.clone();
765        other.header.protocol_version -= 1;
766        assert_eq!(Some(Less), Data::Packet(other).partial_cmp(&packet_data));
767
768        let mut other = packet.clone();
769        other.header.protocol_version += 1;
770        assert_eq!(Some(Greater), Data::Packet(other).partial_cmp(&packet_data));
771
772        let mut other = packet.clone();
773        other.command -= 1;
774        assert_eq!(Some(Less), Data::Packet(other).partial_cmp(&packet_data));
775
776        let mut other = packet.clone();
777        other.command += 1;
778        assert_eq!(Some(Greater), Data::Packet(other).partial_cmp(&packet_data));
779
780        let mut other = packet.clone();
781        other.frame_count ^= 1;
782        assert_eq!(Some(Equal), Data::Packet(other).partial_cmp(&packet_data));
783
784        let mut other = packet.clone();
785        other.frame_data[0] ^= 1;
786        assert_eq!(Some(Equal), Data::Packet(other).partial_cmp(&packet_data));
787
788        // ---- Datagram ----
789        let other = dgram.clone();
790        assert_eq!(Some(Equal), Data::Datagram(other).partial_cmp(&dgram_data));
791
792        let mut other = dgram.clone();
793        other.header.timestamp = other_timestamp;
794        assert_eq!(Some(Equal), Data::Datagram(other).partial_cmp(&dgram_data));
795
796        let mut other = dgram.clone();
797        other.header.channel -= 1;
798        assert_eq!(Some(Less), Data::Datagram(other).partial_cmp(&dgram_data));
799
800        let mut other = dgram.clone();
801        other.header.channel += 1;
802        assert_eq!(
803            Some(Greater),
804            Data::Datagram(other).partial_cmp(&dgram_data)
805        );
806
807        let mut other = dgram.clone();
808        other.header.destination_address += 1; // NOTE(daniel): subtraction would underflow
809        assert_eq!(Some(Less), dgram_data.partial_cmp(&Data::Datagram(other)));
810
811        let mut other = dgram.clone();
812        other.header.destination_address += 1;
813        assert_eq!(
814            Some(Greater),
815            Data::Datagram(other).partial_cmp(&dgram_data)
816        );
817
818        let mut other = dgram.clone();
819        other.header.source_address -= 1;
820        assert_eq!(Some(Less), Data::Datagram(other).partial_cmp(&dgram_data));
821
822        let mut other = dgram.clone();
823        other.header.source_address += 1;
824        assert_eq!(
825            Some(Greater),
826            Data::Datagram(other).partial_cmp(&dgram_data)
827        );
828
829        let mut other = dgram.clone();
830        other.header.protocol_version -= 1;
831        assert_eq!(Some(Less), Data::Datagram(other).partial_cmp(&dgram_data));
832
833        let mut other = dgram.clone();
834        other.header.protocol_version += 1;
835        assert_eq!(
836            Some(Greater),
837            Data::Datagram(other).partial_cmp(&dgram_data)
838        );
839
840        let mut other = dgram.clone();
841        other.command -= 1;
842        assert_eq!(Some(Less), Data::Datagram(other).partial_cmp(&dgram_data));
843
844        let mut other = dgram.clone();
845        other.command += 1;
846        assert_eq!(
847            Some(Greater),
848            Data::Datagram(other).partial_cmp(&dgram_data)
849        );
850
851        let mut other = dgram.clone();
852        other.param16 ^= 1;
853        assert_eq!(Some(Equal), Data::Datagram(other).partial_cmp(&dgram_data));
854
855        let mut other = dgram.clone();
856        other.param32 ^= 1;
857        assert_eq!(Some(Equal), Data::Datagram(other).partial_cmp(&dgram_data));
858
859        // ---- Telegram ----
860        let other = tgram.clone();
861        assert_eq!(Some(Equal), Data::Telegram(other).partial_cmp(&tgram_data));
862
863        let mut other = tgram.clone();
864        other.header.timestamp = other_timestamp;
865        assert_eq!(Some(Equal), Data::Telegram(other).partial_cmp(&tgram_data));
866
867        let mut other = tgram.clone();
868        other.header.channel -= 1;
869        assert_eq!(Some(Less), Data::Telegram(other).partial_cmp(&tgram_data));
870
871        let mut other = tgram.clone();
872        other.header.channel += 1;
873        assert_eq!(
874            Some(Greater),
875            Data::Telegram(other).partial_cmp(&tgram_data)
876        );
877
878        let mut other = tgram.clone();
879        other.header.destination_address -= 1;
880        assert_eq!(Some(Less), Data::Telegram(other).partial_cmp(&tgram_data));
881
882        let mut other = tgram.clone();
883        other.header.destination_address += 1;
884        assert_eq!(
885            Some(Greater),
886            Data::Telegram(other).partial_cmp(&tgram_data)
887        );
888
889        let mut other = tgram.clone();
890        other.header.source_address -= 1;
891        assert_eq!(Some(Less), Data::Telegram(other).partial_cmp(&tgram_data));
892
893        let mut other = tgram.clone();
894        other.header.source_address += 1;
895        assert_eq!(
896            Some(Greater),
897            Data::Telegram(other).partial_cmp(&tgram_data)
898        );
899
900        let mut other = tgram.clone();
901        other.header.protocol_version -= 1;
902        assert_eq!(Some(Less), Data::Telegram(other).partial_cmp(&tgram_data));
903
904        let mut other = tgram.clone();
905        other.header.protocol_version += 1;
906        assert_eq!(
907            Some(Greater),
908            Data::Telegram(other).partial_cmp(&tgram_data)
909        );
910
911        let mut other = tgram.clone();
912        other.command -= 1;
913        assert_eq!(Some(Less), Data::Telegram(other).partial_cmp(&tgram_data));
914
915        let mut other = tgram.clone();
916        other.command += 1;
917        assert_eq!(
918            Some(Greater),
919            Data::Telegram(other).partial_cmp(&tgram_data)
920        );
921
922        let mut other = tgram.clone();
923        other.frame_data[0] ^= 1;
924        assert_eq!(Some(Equal), Data::Telegram(other).partial_cmp(&tgram_data));
925    }
926
927    #[test]
928    fn test_id_hash() {
929        let timestamp = Utc.timestamp(1485688933, 0);
930        let channel = 0x11;
931
932        let data = packet_data(timestamp, channel);
933
934        let result = id_hash(&data);
935        assert_eq!(541127499104566154, result);
936
937        let data = datagram_data(timestamp, channel);
938
939        let result = id_hash(&data);
940        assert_eq!(6066488998843577430, result);
941
942        let data = telegram_data(timestamp, channel);
943
944        let result = id_hash(&data);
945        assert_eq!(2688669052981416192, result);
946    }
947}