11//! CAN Identifiers.
22
33/// Standard 11-bit CAN Identifier (`0..=0x7FF`).
4- #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
4+ #[ derive( Debug , Copy , Clone , Eq , PartialEq , PartialOrd , Ord , Hash ) ]
55pub struct StandardId ( u16 ) ;
66
77impl StandardId {
@@ -40,7 +40,7 @@ impl StandardId {
4040}
4141
4242/// 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 ) ]
4444pub struct ExtendedId ( u32 ) ;
4545
4646impl ExtendedId {
@@ -85,7 +85,7 @@ impl ExtendedId {
8585}
8686
8787/// A CAN Identifier (standard or extended).
88- #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
88+ #[ derive( Debug , Copy , Clone , Eq , PartialEq , Hash ) ]
8989pub enum Id {
9090 /// Standard 11-bit Identifier (`0..=0x7FF`).
9191 Standard ( StandardId ) ,
@@ -94,6 +94,44 @@ pub enum Id {
9494 Extended ( ExtendedId ) ,
9595}
9696
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+
97135impl From < StandardId > for Id {
98136 #[ inline]
99137 fn from ( id : StandardId ) -> Self {
@@ -157,4 +195,15 @@ mod tests {
157195 StandardId :: new( ( ExtendedId :: MAX . 0 >> 18 ) as u16 )
158196 ) ;
159197 }
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+ }
160209}
0 commit comments