@@ -33,11 +33,13 @@ pub mod time;
3333mod net;
3434mod status;
3535
36+ use core:: cmp;
3637pub use net:: * ;
3738pub use status:: Status ;
3839pub use uguid:: { Guid , guid} ;
3940
4041use core:: ffi:: c_void;
42+ use core:: hash:: { Hash , Hasher } ;
4143
4244/// Handle to an event structure.
4345pub type Event = * mut c_void ;
@@ -73,19 +75,34 @@ pub type VirtualAddress = u64;
7375/// This is similar to a `bool`, but allows values other than 0 or 1 to be
7476/// stored without it being undefined behavior.
7577///
76- /// Any non-zero value is treated as logically `true`.
77- #[ derive( Copy , Clone , Debug , Default , PartialEq , Ord , PartialOrd , Eq , Hash ) ]
78+ /// Any non-zero value is treated as logical `true`. The comparison, ordering,
79+ /// and hashing implementations follow that logical interpretation, so all
80+ /// non-zero values compare equal and hash the same way. The original byte is
81+ /// still preserved in the public field; compare the `.0` values directly when
82+ /// the exact raw bit pattern matters.
83+ #[ derive( Copy , Clone , Debug , Default ) ]
7884#[ repr( transparent) ]
7985pub struct Boolean ( pub u8 ) ;
8086
8187impl Boolean {
8288 /// [`Boolean`] representing `true`.
89+ ///
90+ /// # Caution
91+ ///
92+ /// This is only one possible true bit pattern. In UEFI, every non-zero
93+ /// bit pattern is treated as logical `true`.
8394 pub const TRUE : Self = Self ( 1 ) ;
8495
8596 /// [`Boolean`] representing `false`.
8697 pub const FALSE : Self = Self ( 0 ) ;
8798}
8899
100+ impl From < u8 > for Boolean {
101+ fn from ( value : u8 ) -> Self {
102+ Self ( value)
103+ }
104+ }
105+
89106impl From < bool > for Boolean {
90107 fn from ( value : bool ) -> Self {
91108 match value {
@@ -106,6 +123,45 @@ impl From<Boolean> for bool {
106123 }
107124}
108125
126+ impl PartialEq for Boolean {
127+ fn eq ( & self , other : & Self ) -> bool {
128+ match ( self . 0 , other. 0 ) {
129+ ( 0 , 0 ) => true ,
130+ ( 0 , _) => false ,
131+ ( _, 0 ) => false ,
132+ // We handle it as in C: Any bit-pattern != 0 equals true
133+ ( _, _) => true ,
134+ }
135+ }
136+ }
137+
138+ impl Eq for Boolean { }
139+
140+ impl PartialOrd for Boolean {
141+ fn partial_cmp ( & self , other : & Self ) -> Option < cmp:: Ordering > {
142+ Some ( self . cmp ( other) )
143+ }
144+ }
145+
146+ impl Ord for Boolean {
147+ fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
148+ match ( self . 0 , other. 0 ) {
149+ ( 0 , 0 ) => cmp:: Ordering :: Equal ,
150+ ( 0 , _) => cmp:: Ordering :: Less ,
151+ ( _, 0 ) => cmp:: Ordering :: Greater ,
152+ // We handle it as in C: Any bit-pattern != 0 equals true
153+ ( _, _) => cmp:: Ordering :: Equal ,
154+ }
155+ }
156+ }
157+
158+ impl Hash for Boolean {
159+ fn hash < H : Hasher > ( & self , state : & mut H ) {
160+ let seed = if self . 0 == 0 { 0 } else { 1 } ;
161+ state. write_u8 ( seed) ;
162+ }
163+ }
164+
109165#[ cfg( test) ]
110166mod tests {
111167 use super :: * ;
@@ -127,4 +183,48 @@ mod tests {
127183 assert ! ( bool :: from( Boolean ( 0b11111110 ) ) ) ;
128184 assert ! ( bool :: from( Boolean ( 0b11111111 ) ) ) ;
129185 }
186+
187+ #[ test]
188+ fn test_order ( ) {
189+ assert ! ( Boolean :: FALSE < Boolean :: TRUE ) ;
190+ assert ! ( Boolean :: TRUE > Boolean :: FALSE ) ;
191+ }
192+
193+ #[ test]
194+ fn test_equality ( ) {
195+ assert_eq ! ( Boolean ( 0 ) , Boolean ( 0 ) ) ;
196+ assert_ne ! ( Boolean ( 0 ) , Boolean ( 3 ) ) ;
197+ assert_ne ! ( Boolean ( 7 ) , Boolean ( 0 ) ) ;
198+ assert_eq ! ( Boolean ( 1 ) , Boolean ( 1 ) ) ;
199+ assert_eq ! ( Boolean ( 13 ) , Boolean ( 7 ) ) ;
200+ }
201+
202+ // Tests that hash impl matches equal impl
203+ #[ test]
204+ fn test_hash ( ) {
205+ #[ derive( Default ) ]
206+ struct TestHasher ( u64 ) ;
207+
208+ impl Hasher for TestHasher {
209+ fn finish ( & self ) -> u64 {
210+ self . 0
211+ }
212+
213+ fn write ( & mut self , bytes : & [ u8 ] ) {
214+ for byte in bytes {
215+ self . 0 = self . 0 . wrapping_mul ( 257 ) . wrapping_add ( u64:: from ( * byte) ) ;
216+ }
217+ }
218+ }
219+
220+ fn calculate_hash ( value : Boolean ) -> u64 {
221+ let mut hasher = TestHasher :: default ( ) ;
222+ value. hash ( & mut hasher) ;
223+ hasher. finish ( )
224+ }
225+
226+ assert_eq ! ( calculate_hash( Boolean ( 1 ) ) , calculate_hash( Boolean ( 13 ) ) ) ;
227+ assert_eq ! ( calculate_hash( Boolean ( 13 ) ) , calculate_hash( Boolean ( 255 ) ) ) ;
228+ assert_ne ! ( calculate_hash( Boolean ( 0 ) ) , calculate_hash( Boolean ( 13 ) ) ) ;
229+ }
130230}
0 commit comments