1
1
//! CAN Identifiers.
2
2
3
3
/// Standard 11-bit CAN Identifier (`0..=0x7FF`).
4
- #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
4
+ #[ derive( Debug , Copy , Clone , Eq , PartialEq , PartialOrd , Ord , Hash ) ]
5
5
pub struct StandardId ( u16 ) ;
6
6
7
7
impl StandardId {
@@ -40,7 +40,7 @@ impl StandardId {
40
40
}
41
41
42
42
/// Extended 29-bit CAN Identifier (`0..=1FFF_FFFF`).
43
- #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
43
+ #[ derive( Debug , Copy , Clone , Eq , PartialEq , PartialOrd , Ord , Hash ) ]
44
44
pub struct ExtendedId ( u32 ) ;
45
45
46
46
impl ExtendedId {
@@ -85,7 +85,7 @@ impl ExtendedId {
85
85
}
86
86
87
87
/// A CAN Identifier (standard or extended).
88
- #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
88
+ #[ derive( Debug , Copy , Clone , Eq , PartialEq , Hash ) ]
89
89
pub enum Id {
90
90
/// Standard 11-bit Identifier (`0..=0x7FF`).
91
91
Standard ( StandardId ) ,
@@ -94,6 +94,44 @@ pub enum Id {
94
94
Extended ( ExtendedId ) ,
95
95
}
96
96
97
+ /// Implement `Ord` according to the CAN arbitration rules
98
+ ///
99
+ /// When performing arbitration, frames are looked at bit for bit starting
100
+ /// from the beginning. A bit with the value 0 is dominant and a bit with
101
+ /// value of 1 is recessive.
102
+ ///
103
+ /// When two devices are sending frames at the same time, as soon as the first
104
+ /// bit is found which differs, the frame with the corresponding dominant
105
+ /// 0 bit will win and get to send the rest of the frame.
106
+ ///
107
+ /// This implementation of `Ord` for `Id` will take this into consideration
108
+ /// and when comparing two different instances of `Id` the "smallest" will
109
+ /// always be the ID which would form the most dominant frame, all other
110
+ /// things being equal.
111
+ impl Ord for Id {
112
+ fn cmp ( & self , other : & Self ) -> core:: cmp:: Ordering {
113
+ let split_id = |id : & Id | {
114
+ let ( standard_id_part, ide_bit, extended_id_part) = match id {
115
+ Id :: Standard ( StandardId ( x) ) => ( * x, 0 , 0 ) ,
116
+ Id :: Extended ( x) => (
117
+ x. standard_id ( ) . 0 ,
118
+ 1 ,
119
+ x. 0 & ( ( 1 << 18 ) - 1 ) , // Bit ID-17 to ID-0
120
+ ) ,
121
+ } ;
122
+ ( standard_id_part, ide_bit, extended_id_part)
123
+ } ;
124
+
125
+ split_id ( self ) . cmp ( & split_id ( other) )
126
+ }
127
+ }
128
+
129
+ impl PartialOrd for Id {
130
+ fn partial_cmp ( & self , other : & Id ) -> Option < core:: cmp:: Ordering > {
131
+ Some ( self . cmp ( other) )
132
+ }
133
+ }
134
+
97
135
impl From < StandardId > for Id {
98
136
#[ inline]
99
137
fn from ( id : StandardId ) -> Self {
@@ -157,4 +195,15 @@ mod tests {
157
195
StandardId :: new( ( ExtendedId :: MAX . 0 >> 18 ) as u16 )
158
196
) ;
159
197
}
198
+
199
+ #[ test]
200
+ fn cmp_id ( ) {
201
+ assert ! ( StandardId :: ZERO < StandardId :: MAX ) ;
202
+ assert ! ( ExtendedId :: ZERO < ExtendedId :: MAX ) ;
203
+
204
+ assert ! ( Id :: Standard ( StandardId :: ZERO ) < Id :: Extended ( ExtendedId :: ZERO ) ) ;
205
+ assert ! ( Id :: Extended ( ExtendedId :: ZERO ) < Id :: Extended ( ExtendedId :: MAX ) ) ;
206
+ assert ! ( Id :: Extended ( ExtendedId ( ( 1 << 11 ) - 1 ) ) < Id :: Standard ( StandardId ( 1 ) ) ) ;
207
+ assert ! ( Id :: Standard ( StandardId ( 1 ) ) < Id :: Extended ( ExtendedId :: MAX ) ) ;
208
+ }
160
209
}
0 commit comments