@@ -45,61 +45,8 @@ impl Choice {
4545 /// Equivalent of [`true`].
4646 pub const TRUE : Self = Self ( 1 ) ;
4747
48- /// Convert `Choice` into a `bool`.
49- ///
50- /// <div class = "warning">
51- /// <b>Security Warning</b>
52- ///
53- /// Using this function will introduce timing variability, since computing this at all currently
54- /// requires a branch.
55- ///
56- /// This is intended to be used as either the one and only branch at the end of a constant-time
57- /// operation to e.g. differentiate between success and failure, or in contexts where
58- /// constant-time doesn't matter, e.g. variable-time code that operates on "maybe secret" types
59- /// which aren't secrets in a particular context.
60- ///
61- /// If you are trying to use this in the context of a constant-time operation, be warned that
62- /// the small amount of timing variability it introduces can potentially be exploited. Whenever
63- /// possible, prefer fully constant-time approaches instead.
64- /// </div>
65- // TODO(tarcieri): `const fn` when MSRV 1.86
66- pub fn to_bool ( self ) -> bool {
67- self . to_u8 ( ) != 0
68- }
69-
70- /// Convert [`Choice`] to a `u8`, attempting to apply a "best effort" optimization barrier.
71- // TODO(tarcieri): `const fn` when MSRV 1.86
72- pub fn to_u8 ( self ) -> u8 {
73- // `black_box` is documented as working on a "best effort" basis. That's fine, this type is
74- // likewise documented as only working on a "best effort" basis itself. The only way we
75- // rely on `black_box` for correctness is it behaving as the identity function.
76- core:: hint:: black_box ( self . 0 )
77- }
78-
79- /// HACK: workaround to allow `const fn` boolean support on Rust 1.85.
80- ///
81- /// This does not apply `black_box` to the output.
82- ///
83- /// <div class = "warning">
84- /// <b>Security Warning</b>
85- ///
86- /// See the security warnings for [`Choice::to_bool`].
87- /// </div>
88- // TODO(tarcieri): deprecate/remove this in favor of `to_bool` when MSRV is Rust 1.86
89- pub const fn to_bool_vartime ( self ) -> bool {
90- self . 0 != 0
91- }
92-
93- /// HACK: workaround to allow `const fn` boolean support on Rust 1.85.
94- ///
95- /// This does not apply `black_box` to the output.
96- // TODO(tarcieri): deprecate/remove this in favor of `to_u8` when MSRV is Rust 1.86
97- pub const fn to_u8_vartime ( self ) -> u8 {
98- self . 0
99- }
100-
10148 //
102- // Bitwise ops
49+ // `const fn` bitwise ops
10350 //
10451
10552 /// Apply an `and` conditional to the given [`Choice`]s.
@@ -128,7 +75,7 @@ impl Choice {
12875 }
12976
13077 //
131- // Comparison ops
78+ // `const fn` comparison ops
13279 //
13380
13481 /// `const fn` equality operation.
@@ -355,14 +302,91 @@ impl Choice {
355302 a ^ ( self . to_u128_mask ( ) & ( a ^ b) )
356303 }
357304
305+ //
306+ // Output conversion methods
307+ //
308+
309+ /// Convert `Choice` into a `bool`.
310+ ///
311+ /// <div class = "warning">
312+ /// <b>Security Warning</b>
313+ ///
314+ /// Using this function will introduce timing variability, since computing this at all currently
315+ /// requires a branch.
316+ ///
317+ /// This is intended to be used as either the one and only branch at the end of a constant-time
318+ /// operation to e.g. differentiate between success and failure, or in contexts where
319+ /// constant-time doesn't matter, e.g. variable-time code that operates on "maybe secret" types
320+ /// which aren't secrets in a particular context.
321+ ///
322+ /// If you are trying to use this in the context of a constant-time operation, be warned that
323+ /// the small amount of timing variability it introduces can potentially be exploited. Whenever
324+ /// possible, prefer fully constant-time approaches instead.
325+ /// </div>
326+ // TODO(tarcieri): `const fn` when MSRV 1.86
327+ pub fn to_bool ( self ) -> bool {
328+ self . to_u8 ( ) != 0
329+ }
330+
331+ /// Convert [`Choice`] to a `u8`, attempting to apply a "best effort" optimization barrier.
332+ // TODO(tarcieri): `const fn` when MSRV 1.86
333+ pub fn to_u8 ( self ) -> u8 {
334+ // `black_box` is documented as working on a "best effort" basis. That's fine, this type is
335+ // likewise documented as only working on a "best effort" basis itself. The only way we
336+ // rely on `black_box` for correctness is it behaving as the identity function.
337+ core:: hint:: black_box ( self . 0 )
338+ }
339+
340+ /// HACK: workaround to allow `const fn` boolean support on Rust 1.85.
341+ ///
342+ /// This does not apply `black_box` to the output.
343+ ///
344+ /// <div class = "warning">
345+ /// <b>Security Warning</b>
346+ ///
347+ /// See the security warnings for [`Choice::to_bool`].
348+ /// </div>
349+ // TODO(tarcieri): deprecate/remove this in favor of `to_bool` when MSRV is Rust 1.86
350+ pub const fn to_bool_vartime ( self ) -> bool {
351+ self . 0 != 0
352+ }
353+
354+ /// HACK: workaround to allow `const fn` boolean support on Rust 1.85.
355+ ///
356+ /// This does not apply `black_box` to the output.
357+ // TODO(tarcieri): deprecate/remove this in favor of `to_u8` when MSRV is Rust 1.86
358+ pub const fn to_u8_vartime ( self ) -> u8 {
359+ self . 0
360+ }
361+
362+ /// Create a `u8` bitmask.
363+ ///
364+ /// # Returns
365+ /// - `0` for `Choice::FALSE`
366+ /// - `u8::MAX` for `Choice::TRUE`
367+ #[ inline]
368+ pub const fn to_u8_mask ( self ) -> u8 {
369+ self . 0 . wrapping_neg ( )
370+ }
371+
372+ /// Create a `u16` bitmask.
373+ ///
374+ /// # Returns
375+ /// - `0` for `Choice::FALSE`
376+ /// - `u16::MAX` for `Choice::TRUE`
377+ #[ inline]
378+ pub const fn to_u16_mask ( self ) -> u16 {
379+ ( self . 0 as u16 ) . wrapping_neg ( )
380+ }
381+
358382 /// Create a `u32` bitmask.
359383 ///
360384 /// # Returns
361385 /// - `0` for `Choice::FALSE`
362386 /// - `u32::MAX` for `Choice::TRUE`
363387 #[ inline]
364388 pub const fn to_u32_mask ( self ) -> u32 {
365- ( self . 0 as u32 & 1 ) . wrapping_neg ( )
389+ ( self . 0 as u32 ) . wrapping_neg ( )
366390 }
367391
368392 /// Create a `u64` bitmask.
@@ -372,7 +396,7 @@ impl Choice {
372396 /// - `u64::MAX` for `Choice::TRUE`
373397 #[ inline]
374398 pub const fn to_u64_mask ( self ) -> u64 {
375- ( self . 0 as u64 & 1 ) . wrapping_neg ( )
399+ ( self . 0 as u64 ) . wrapping_neg ( )
376400 }
377401
378402 /// Create a `u128` bitmask.
@@ -382,7 +406,7 @@ impl Choice {
382406 /// - `u128::MAX` for `Choice::TRUE`
383407 #[ inline]
384408 pub const fn to_u128_mask ( self ) -> u128 {
385- ( self . 0 as u128 & 1 ) . wrapping_neg ( )
409+ ( self . 0 as u128 ) . wrapping_neg ( )
386410 }
387411}
388412
@@ -553,18 +577,6 @@ mod tests {
553577 assert_eq ! ( a. ct_select( & b, Choice :: TRUE ) . to_bool( ) , b. to_bool( ) ) ;
554578 }
555579
556- #[ test]
557- fn to_bool ( ) {
558- assert ! ( !Choice :: FALSE . to_bool( ) ) ;
559- assert ! ( Choice :: TRUE . to_bool( ) ) ;
560- }
561-
562- #[ test]
563- fn to_u8 ( ) {
564- assert_eq ! ( Choice :: FALSE . to_u8( ) , 0 ) ;
565- assert_eq ! ( Choice :: TRUE . to_u8( ) , 1 ) ;
566- }
567-
568580 #[ test]
569581 fn and ( ) {
570582 assert_eq ! ( ( Choice :: FALSE & Choice :: FALSE ) . to_u8( ) , 0 ) ;
@@ -813,4 +825,46 @@ mod tests {
813825 assert_eq ! ( Choice :: TRUE . select_u128( a, b) , b) ;
814826 assert_eq ! ( Choice :: FALSE . select_u128( a, b) , a) ;
815827 }
828+
829+ #[ test]
830+ fn to_bool ( ) {
831+ assert ! ( !Choice :: FALSE . to_bool( ) ) ;
832+ assert ! ( Choice :: TRUE . to_bool( ) ) ;
833+ }
834+
835+ #[ test]
836+ fn to_u8 ( ) {
837+ assert_eq ! ( Choice :: FALSE . to_u8( ) , 0 ) ;
838+ assert_eq ! ( Choice :: TRUE . to_u8( ) , 1 ) ;
839+ }
840+
841+ #[ test]
842+ fn to_u8_mask ( ) {
843+ assert_eq ! ( Choice :: FALSE . to_u8_mask( ) , 0 ) ;
844+ assert_eq ! ( Choice :: TRUE . to_u8_mask( ) , u8 :: MAX ) ;
845+ }
846+
847+ #[ test]
848+ fn to_u16_mask ( ) {
849+ assert_eq ! ( Choice :: FALSE . to_u16_mask( ) , 0 ) ;
850+ assert_eq ! ( Choice :: TRUE . to_u16_mask( ) , u16 :: MAX ) ;
851+ }
852+
853+ #[ test]
854+ fn to_u32_mask ( ) {
855+ assert_eq ! ( Choice :: FALSE . to_u32_mask( ) , 0 ) ;
856+ assert_eq ! ( Choice :: TRUE . to_u32_mask( ) , u32 :: MAX ) ;
857+ }
858+
859+ #[ test]
860+ fn to_u64_mask ( ) {
861+ assert_eq ! ( Choice :: FALSE . to_u64_mask( ) , 0 ) ;
862+ assert_eq ! ( Choice :: TRUE . to_u64_mask( ) , u64 :: MAX ) ;
863+ }
864+
865+ #[ test]
866+ fn to_u128_mask ( ) {
867+ assert_eq ! ( Choice :: FALSE . to_u128_mask( ) , 0 ) ;
868+ assert_eq ! ( Choice :: TRUE . to_u128_mask( ) , u128 :: MAX ) ;
869+ }
816870}
0 commit comments