Skip to main content

ctutils/
choice.rs

1use crate::{CtAssign, CtAssignSlice, CtEq, CtEqSlice, CtSelectUsingCtAssign};
2use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
3
4#[cfg(feature = "subtle")]
5use crate::CtSelect;
6
7/// Bitwise less-than-or equal: returns `1` if `x <= y`, and otherwise returns `0`.
8///
9/// See "Hacker's Delight" 2nd edition, section 2-12 (Comparison predicates)
10macro_rules! bitle {
11    ($x:expr, $y:expr, $bits:expr) => {
12        (((!$x) | $y) & (($x ^ $y) | !($y.wrapping_sub($x)))) >> ($bits - 1)
13    };
14}
15
16/// Bitwise less-than: returns `1` if `x < y`, and otherwise returns `0`.
17///
18/// See "Hacker's Delight" 2nd edition, section 2-12 (Comparison predicates)
19macro_rules! bitlt {
20    ($x:expr, $y:expr, $bits:expr) => {
21        (((!$x) & $y) | (((!$x) | $y) & $x.wrapping_sub($y))) >> ($bits - 1)
22    };
23}
24
25/// Bitwise non-zero: returns `1` if `x != 0`, and otherwise returns `0`.
26macro_rules! bitnz {
27    ($value:expr, $bits:expr) => {
28        ($value | $value.wrapping_neg()) >> ($bits - 1)
29    };
30}
31
32/// Constant-time analogue of `bool` providing a "best effort" optimization barrier.
33///
34/// This type attempts to hint to the compiler and its codegen backends that optimizations should
35/// not be applied which depend on specific values of this type.
36///
37/// This is used as a "belt-and-suspenders" defense in addition to mechanisms like
38/// constant-time predication intrinsics provided by the [`cmov`] crate, and is never expected to be
39/// the only line of defense.
40// NOTE: we deliberately do NOT impl `Eq`, `Hash`, `PartialEq`, etc. See #1315
41#[derive(Copy, Clone, Debug)]
42pub struct Choice(pub(crate) u8);
43
44impl Choice {
45    /// Equivalent of [`false`].
46    pub const FALSE: Self = Self(0);
47
48    /// Equivalent of [`true`].
49    pub const TRUE: Self = Self(1);
50
51    //
52    // `const fn` bitwise ops
53    //
54
55    /// Apply an `and` conditional to the given [`Choice`]s.
56    #[inline]
57    #[must_use]
58    pub const fn and(self, rhs: Choice) -> Choice {
59        Self(self.0 & rhs.0)
60    }
61
62    /// Apply an `or` conditional to the given [`Choice`]s.
63    #[inline]
64    #[must_use]
65    pub const fn or(self, rhs: Choice) -> Choice {
66        Self(self.0 | rhs.0)
67    }
68
69    /// Apply an `xor` conditional to the given [`Choice`]s.
70    #[inline]
71    #[must_use]
72    pub const fn xor(self, rhs: Choice) -> Choice {
73        Self(self.0 ^ rhs.0)
74    }
75
76    /// Compute the boolean inverse of `self`.
77    #[inline]
78    #[must_use]
79    pub const fn not(self) -> Choice {
80        // NOTE: assumes self.0 is `0` or `1` as checked in constructor
81        Self(self.0 ^ 1)
82    }
83
84    //
85    // `const fn` comparison ops
86    //
87
88    /// `const fn` equality operation.
89    #[inline]
90    #[must_use]
91    pub const fn eq(self, other: Self) -> Self {
92        Self::ne(self, other).not()
93    }
94
95    /// `const fn` not equal operation.
96    #[inline]
97    #[must_use]
98    pub const fn ne(self, other: Self) -> Self {
99        Self::xor(self, other)
100    }
101
102    //
103    // `const fn` constructor methods
104    //
105
106    // i64
107
108    /// Returns [`Choice::TRUE`] if `x == y`, and [`Choice::FALSE`] otherwise.
109    #[inline]
110    #[must_use]
111    #[allow(clippy::cast_sign_loss)]
112    pub const fn from_i64_eq(x: i64, y: i64) -> Self {
113        // TODO(tarcieri): use `cast_unsigned` when MSRV is 1.87
114        Self::from_u64_nz(x as u64 ^ y as u64).not()
115    }
116
117    // u8
118
119    /// Returns [`Choice::TRUE`] if `x == y`, and [`Choice::FALSE`] otherwise.
120    #[inline]
121    #[must_use]
122    pub const fn from_u8_eq(x: u8, y: u8) -> Self {
123        Self::from_u8_nz(x ^ y).not()
124    }
125
126    /// Returns [`Choice::TRUE`] if `x <= y` and [`Choice::FALSE`] otherwise.
127    #[inline]
128    #[must_use]
129    pub const fn from_u8_le(x: u8, y: u8) -> Self {
130        Self::from_u8_lsb(bitle!(x, y, u8::BITS))
131    }
132
133    /// Initialize from the least significant bit of a `u8`.
134    #[inline]
135    #[must_use]
136    pub const fn from_u8_lsb(value: u8) -> Self {
137        Self(value & 0x1)
138    }
139
140    /// Returns [`Choice::TRUE`] if `x < y`, and [`Choice::FALSE`] otherwise.
141    #[inline]
142    #[must_use]
143    pub const fn from_u8_lt(x: u8, y: u8) -> Self {
144        Self::from_u8_lsb(bitlt!(x, y, u8::BITS))
145    }
146
147    /// Returns [`Choice::TRUE`] if `value != 0`, and [`Choice::FALSE`] otherwise.
148    #[inline]
149    #[must_use]
150    pub const fn from_u8_nz(value: u8) -> Self {
151        Self::from_u8_lsb(bitnz!(value, u8::BITS))
152    }
153
154    // u16
155
156    /// Returns [`Choice::TRUE`] if `x == y`, and [`Choice::FALSE`] otherwise.
157    #[inline]
158    #[must_use]
159    pub const fn from_u16_eq(x: u16, y: u16) -> Self {
160        Self::from_u16_nz(x ^ y).not()
161    }
162
163    /// Returns [`Choice::TRUE`] if `x <= y` and [`Choice::FALSE`] otherwise.
164    #[inline]
165    #[must_use]
166    pub const fn from_u16_le(x: u16, y: u16) -> Self {
167        Self::from_u16_lsb(bitle!(x, y, u16::BITS))
168    }
169
170    /// Initialize from the least significant bit of a `u16`.
171    #[inline]
172    #[must_use]
173    pub const fn from_u16_lsb(value: u16) -> Self {
174        Self((value & 0x1) as u8)
175    }
176
177    /// Returns [`Choice::TRUE`] if `x < y`, and [`Choice::FALSE`] otherwise.
178    #[inline]
179    #[must_use]
180    pub const fn from_u16_lt(x: u16, y: u16) -> Self {
181        Self::from_u16_lsb(bitlt!(x, y, u16::BITS))
182    }
183
184    /// Returns [`Choice::TRUE`] if `value != 0`, and [`Choice::FALSE`] otherwise.
185    #[inline]
186    #[must_use]
187    pub const fn from_u16_nz(value: u16) -> Self {
188        Self::from_u16_lsb(bitnz!(value, u16::BITS))
189    }
190
191    // u32
192
193    /// Returns [`Choice::TRUE`] if `x == y`, and [`Choice::FALSE`] otherwise.
194    #[inline]
195    #[must_use]
196    pub const fn from_u32_eq(x: u32, y: u32) -> Self {
197        Self::from_u32_nz(x ^ y).not()
198    }
199
200    /// Returns [`Choice::TRUE`] if `x <= y` and [`Choice::FALSE`] otherwise.
201    #[inline]
202    #[must_use]
203    pub const fn from_u32_le(x: u32, y: u32) -> Self {
204        Self::from_u32_lsb(bitle!(x, y, u32::BITS))
205    }
206
207    /// Initialize from the least significant bit of a `u32`.
208    #[inline]
209    #[must_use]
210    pub const fn from_u32_lsb(value: u32) -> Self {
211        Self((value & 0x1) as u8)
212    }
213
214    /// Returns [`Choice::TRUE`] if `x < y`, and [`Choice::FALSE`] otherwise.
215    #[inline]
216    #[must_use]
217    pub const fn from_u32_lt(x: u32, y: u32) -> Self {
218        Self::from_u32_lsb(bitlt!(x, y, u32::BITS))
219    }
220
221    /// Returns [`Choice::TRUE`] if `value != 0`, and [`Choice::FALSE`] otherwise.
222    #[inline]
223    #[must_use]
224    pub const fn from_u32_nz(value: u32) -> Self {
225        Self::from_u32_lsb(bitnz!(value, u32::BITS))
226    }
227
228    // u64
229
230    /// Returns [`Choice::TRUE`] if `x == y`, and [`Choice::FALSE`] otherwise.
231    #[inline]
232    #[must_use]
233    pub const fn from_u64_eq(x: u64, y: u64) -> Self {
234        Self::from_u64_nz(x ^ y).not()
235    }
236
237    /// Returns [`Choice::TRUE`] if `x <= y` and [`Choice::FALSE`] otherwise.
238    #[inline]
239    #[must_use]
240    pub const fn from_u64_le(x: u64, y: u64) -> Self {
241        Self::from_u64_lsb(bitle!(x, y, u64::BITS))
242    }
243
244    /// Initialize from the least significant bit of a `u64`.
245    #[inline]
246    #[must_use]
247    pub const fn from_u64_lsb(value: u64) -> Self {
248        Self((value & 0x1) as u8)
249    }
250
251    /// Returns [`Choice::TRUE`] if `x < y`, and [`Choice::FALSE`] otherwise.
252    #[inline]
253    #[must_use]
254    pub const fn from_u64_lt(x: u64, y: u64) -> Self {
255        Self::from_u64_lsb(bitlt!(x, y, u64::BITS))
256    }
257
258    /// Returns [`Choice::TRUE`] if `value != 0`, and [`Choice::FALSE`] otherwise.
259    #[inline]
260    #[must_use]
261    pub const fn from_u64_nz(value: u64) -> Self {
262        Self::from_u64_lsb(bitnz!(value, u64::BITS))
263    }
264
265    // u128
266
267    /// Returns [`Choice::TRUE`] if `x == y`, and [`Choice::FALSE`] otherwise.
268    #[inline]
269    #[must_use]
270    pub const fn from_u128_eq(x: u128, y: u128) -> Self {
271        Self::from_u128_nz(x ^ y).not()
272    }
273
274    /// Returns [`Choice::TRUE`] if `x <= y` and [`Choice::FALSE`] otherwise.
275    #[inline]
276    #[must_use]
277    pub const fn from_u128_le(x: u128, y: u128) -> Self {
278        Self::from_u128_lsb(bitle!(x, y, u128::BITS))
279    }
280
281    /// Initialize from the least significant bit of a `u128`.
282    #[inline]
283    #[must_use]
284    pub const fn from_u128_lsb(value: u128) -> Self {
285        Self((value & 1) as u8)
286    }
287
288    /// Returns [`Choice::TRUE`] if `x < y`, and [`Choice::FALSE`] otherwise.
289    #[inline]
290    #[must_use]
291    pub const fn from_u128_lt(x: u128, y: u128) -> Self {
292        Self::from_u128_lsb(bitlt!(x, y, u128::BITS))
293    }
294
295    /// Returns [`Choice::TRUE`] if `value != 0`, and [`Choice::FALSE`] otherwise.
296    #[inline]
297    #[must_use]
298    pub const fn from_u128_nz(value: u128) -> Self {
299        Self::from_u128_lsb(bitnz!(value, u128::BITS))
300    }
301
302    //
303    // `const fn` predication methods
304    //
305
306    /// `const fn` helper: return `b` if `self` is [`Choice::TRUE`], otherwise return `a`.
307    ///
308    /// Only use this instead of the [`CtSelect`] trait in the event you're in a `const fn` context
309    /// and can't use the trait. The former will provide better constant-time assurances.
310    #[inline]
311    #[must_use]
312    #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
313    pub const fn select_i64(self, a: i64, b: i64) -> i64 {
314        // TODO(tarcieri): use `cast_signed` when MSRV is 1.87
315        self.select_u64(a as u64, b as u64) as i64
316    }
317
318    /// `const fn` helper: return `b` if `self` is [`Choice::TRUE`], otherwise return `a`.
319    ///
320    /// Only use this instead of the [`CtSelect`] trait in the event you're in a `const fn` context
321    /// and can't use the trait. The former will provide better constant-time assurances.
322    #[inline]
323    #[must_use]
324    pub const fn select_u8(self, a: u8, b: u8) -> u8 {
325        a ^ (self.to_u8_mask() & (a ^ b))
326    }
327
328    /// `const fn` helper: return `b` if `self` is [`Choice::TRUE`], otherwise return `a`.
329    ///
330    /// Only use this instead of the [`CtSelect`] trait in the event you're in a `const fn` context
331    /// and can't use the trait. The former will provide better constant-time assurances.
332    #[inline]
333    #[must_use]
334    pub const fn select_u16(self, a: u16, b: u16) -> u16 {
335        a ^ (self.to_u16_mask() & (a ^ b))
336    }
337
338    /// `const fn` helper: return `b` if `self` is [`Choice::TRUE`], otherwise return `a`.
339    ///
340    /// Only use this instead of the [`CtSelect`] trait in the event you're in a `const fn` context
341    /// and can't use the trait. The former will provide better constant-time assurances.
342    #[inline]
343    #[must_use]
344    pub const fn select_u32(self, a: u32, b: u32) -> u32 {
345        a ^ (self.to_u32_mask() & (a ^ b))
346    }
347
348    /// `const fn` helper: return `b` if `self` is [`Choice::TRUE`], otherwise return `a`.
349    ///
350    /// Only use this instead of the [`CtSelect`] trait in the event you're in a `const fn` context
351    /// and can't use the trait. The former will provide better constant-time assurances.
352    #[inline]
353    #[must_use]
354    pub const fn select_u64(self, a: u64, b: u64) -> u64 {
355        a ^ (self.to_u64_mask() & (a ^ b))
356    }
357
358    /// `const fn` helper: return `b` if `self` is [`Choice::TRUE`], otherwise return `a`.
359    ///
360    /// Only use this instead of the [`CtSelect`] trait in the event you're in a `const fn` context
361    /// and can't use the trait. The former will provide better constant-time assurances.
362    #[inline]
363    #[must_use]
364    pub const fn select_u128(self, a: u128, b: u128) -> u128 {
365        a ^ (self.to_u128_mask() & (a ^ b))
366    }
367
368    //
369    // Output conversion methods
370    //
371
372    /// Convert `Choice` into a `bool`.
373    ///
374    /// <div class = "warning">
375    /// <b>Security Warning</b>
376    ///
377    /// Using this function will introduce timing variability, since computing this at all currently
378    /// requires a branch.
379    ///
380    /// This is intended to be used as either the one and only branch at the end of a constant-time
381    /// operation to e.g. differentiate between success and failure, or in contexts where
382    /// constant-time doesn't matter, e.g. variable-time code that operates on "maybe secret" types
383    /// which aren't secrets in a particular context.
384    ///
385    /// If you are trying to use this in the context of a constant-time operation, be warned that
386    /// the small amount of timing variability it introduces can potentially be exploited. Whenever
387    /// possible, prefer fully constant-time approaches instead.
388    /// </div>
389    // TODO(tarcieri): `const fn` when MSRV 1.86
390    #[must_use]
391    pub fn to_bool(self) -> bool {
392        self.to_u8() != 0
393    }
394
395    /// Convert [`Choice`] to a `u8`, attempting to apply a "best effort" optimization barrier.
396    // TODO(tarcieri): `const fn` when MSRV 1.86
397    #[must_use]
398    pub fn to_u8(self) -> u8 {
399        // `black_box` is documented as working on a "best effort" basis. That's fine, this type is
400        // likewise documented as only working on a "best effort" basis itself. The only way we
401        // rely on `black_box` for correctness is it behaving as the identity function.
402        core::hint::black_box(self.0)
403    }
404
405    /// HACK: workaround to allow `const fn` boolean support on Rust 1.85.
406    ///
407    /// This does not apply `black_box` to the output.
408    ///
409    /// <div class = "warning">
410    /// <b>Security Warning</b>
411    ///
412    /// See the security warnings for [`Choice::to_bool`].
413    /// </div>
414    // TODO(tarcieri): deprecate/remove this in favor of `to_bool` when MSRV is Rust 1.86
415    #[must_use]
416    pub const fn to_bool_vartime(self) -> bool {
417        self.0 != 0
418    }
419
420    /// HACK: workaround to allow `const fn` boolean support on Rust 1.85.
421    ///
422    /// This does not apply `black_box` to the output.
423    // TODO(tarcieri): deprecate/remove this in favor of `to_u8` when MSRV is Rust 1.86
424    #[must_use]
425    pub const fn to_u8_vartime(self) -> u8 {
426        self.0
427    }
428
429    /// Create a `u8` bitmask.
430    ///
431    /// # Returns
432    /// - `0` for `Choice::FALSE`
433    /// - `u8::MAX` for `Choice::TRUE`
434    #[inline]
435    #[must_use]
436    pub const fn to_u8_mask(self) -> u8 {
437        self.0.wrapping_neg()
438    }
439
440    /// Create a `u16` bitmask.
441    ///
442    /// # Returns
443    /// - `0` for `Choice::FALSE`
444    /// - `u16::MAX` for `Choice::TRUE`
445    #[inline]
446    #[must_use]
447    pub const fn to_u16_mask(self) -> u16 {
448        (self.0 as u16).wrapping_neg()
449    }
450
451    /// Create a `u32` bitmask.
452    ///
453    /// # Returns
454    /// - `0` for `Choice::FALSE`
455    /// - `u32::MAX` for `Choice::TRUE`
456    #[inline]
457    #[must_use]
458    pub const fn to_u32_mask(self) -> u32 {
459        (self.0 as u32).wrapping_neg()
460    }
461
462    /// Create a `u64` bitmask.
463    ///
464    /// # Returns
465    /// - `0` for `Choice::FALSE`
466    /// - `u64::MAX` for `Choice::TRUE`
467    #[inline]
468    #[must_use]
469    pub const fn to_u64_mask(self) -> u64 {
470        (self.0 as u64).wrapping_neg()
471    }
472
473    /// Create a `u128` bitmask.
474    ///
475    /// # Returns
476    /// - `0` for `Choice::FALSE`
477    /// - `u128::MAX` for `Choice::TRUE`
478    #[inline]
479    #[must_use]
480    pub const fn to_u128_mask(self) -> u128 {
481        (self.0 as u128).wrapping_neg()
482    }
483}
484
485impl BitAnd for Choice {
486    type Output = Choice;
487
488    #[inline]
489    fn bitand(self, rhs: Choice) -> Choice {
490        self.and(rhs)
491    }
492}
493
494impl BitAndAssign for Choice {
495    #[inline]
496    fn bitand_assign(&mut self, rhs: Choice) {
497        *self = *self & rhs;
498    }
499}
500
501impl BitOr for Choice {
502    type Output = Choice;
503
504    #[inline]
505    fn bitor(self, rhs: Choice) -> Choice {
506        self.or(rhs)
507    }
508}
509
510impl BitOrAssign for Choice {
511    #[inline]
512    fn bitor_assign(&mut self, rhs: Choice) {
513        *self = *self | rhs;
514    }
515}
516
517impl BitXor for Choice {
518    type Output = Choice;
519
520    #[inline]
521    fn bitxor(self, rhs: Choice) -> Choice {
522        Choice(self.0 ^ rhs.0)
523    }
524}
525
526impl BitXorAssign for Choice {
527    #[inline]
528    fn bitxor_assign(&mut self, rhs: Choice) {
529        *self = *self ^ rhs;
530    }
531}
532
533impl CtAssign for Choice {
534    #[inline]
535    fn ct_assign(&mut self, other: &Self, choice: Choice) {
536        self.0.ct_assign(&other.0, choice);
537    }
538}
539impl CtAssignSlice for Choice {}
540impl CtSelectUsingCtAssign for Choice {}
541
542impl CtEq for Choice {
543    #[inline]
544    fn ct_eq(&self, other: &Self) -> Self {
545        self.0.ct_eq(&other.0)
546    }
547}
548impl CtEqSlice for Choice {}
549
550/// DEPRECATED: this exists to aid migrating code from `subtle`. Use `Choice::from_u8_lsb` instead.
551///
552/// <div class="warning">
553/// <b>Note</b>
554///
555/// Rust doesn't actually let us deprecate an impl block, however this comment is here to
556/// discourage future use and warn that this will be removed in a future release.
557/// </div>
558impl From<u8> for Choice {
559    fn from(value: u8) -> Self {
560        Choice::from_u8_lsb(value)
561    }
562}
563
564impl From<Choice> for u8 {
565    fn from(choice: Choice) -> u8 {
566        choice.to_u8()
567    }
568}
569
570/// Convert `Choice` into a `bool`.
571///
572/// <div class = "warning">
573/// <b>Security Warning</b>
574///
575/// Using this function will introduce timing variability, since computing this at all currently
576/// requires a branch.
577///
578/// See the security warnings for [`Choice::to_bool`].
579/// </div>
580impl From<Choice> for bool {
581    fn from(choice: Choice) -> bool {
582        choice.to_bool()
583    }
584}
585
586impl Not for Choice {
587    type Output = Choice;
588
589    #[inline]
590    fn not(self) -> Choice {
591        self.not()
592    }
593}
594
595#[cfg(feature = "subtle")]
596impl From<subtle::Choice> for Choice {
597    #[inline]
598    fn from(choice: subtle::Choice) -> Choice {
599        Choice(choice.unwrap_u8())
600    }
601}
602
603#[cfg(feature = "subtle")]
604impl From<Choice> for subtle::Choice {
605    #[inline]
606    fn from(choice: Choice) -> subtle::Choice {
607        subtle::Choice::from(choice.0)
608    }
609}
610
611#[cfg(feature = "subtle")]
612impl subtle::ConditionallySelectable for Choice {
613    #[inline]
614    fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
615        CtSelect::ct_select(a, b, choice.into())
616    }
617}
618
619#[cfg(feature = "subtle")]
620impl subtle::ConstantTimeEq for Choice {
621    #[inline]
622    fn ct_eq(&self, other: &Self) -> subtle::Choice {
623        CtEq::ct_eq(self, other).into()
624    }
625}
626
627#[cfg(test)]
628mod tests {
629    use super::Choice;
630    use crate::{CtEq, CtSelect};
631
632    #[test]
633    fn ct_eq() {
634        let a = Choice::TRUE;
635        let b = Choice::TRUE;
636        let c = Choice::FALSE;
637
638        assert!(a.ct_eq(&b).to_bool());
639        assert!(!a.ct_eq(&c).to_bool());
640        assert!(!b.ct_eq(&c).to_bool());
641
642        assert!(!a.ct_ne(&b).to_bool());
643        assert!(a.ct_ne(&c).to_bool());
644        assert!(b.ct_ne(&c).to_bool());
645    }
646
647    #[test]
648    fn ct_select() {
649        let a = Choice::FALSE;
650        let b = Choice::TRUE;
651        assert_eq!(a.ct_select(&b, Choice::FALSE).to_bool(), a.to_bool());
652        assert_eq!(a.ct_select(&b, Choice::TRUE).to_bool(), b.to_bool());
653    }
654
655    #[test]
656    fn and() {
657        assert_eq!((Choice::FALSE & Choice::FALSE).to_u8(), 0);
658        assert_eq!((Choice::TRUE & Choice::FALSE).to_u8(), 0);
659        assert_eq!((Choice::FALSE & Choice::TRUE).to_u8(), 0);
660        assert_eq!((Choice::TRUE & Choice::TRUE).to_u8(), 1);
661    }
662
663    #[test]
664    fn or() {
665        assert_eq!((Choice::FALSE | Choice::FALSE).to_u8(), 0);
666        assert_eq!((Choice::TRUE | Choice::FALSE).to_u8(), 1);
667        assert_eq!((Choice::FALSE | Choice::TRUE).to_u8(), 1);
668        assert_eq!((Choice::TRUE | Choice::TRUE).to_u8(), 1);
669    }
670
671    #[test]
672    fn xor() {
673        assert_eq!((Choice::FALSE ^ Choice::FALSE).to_u8(), 0);
674        assert_eq!((Choice::TRUE ^ Choice::FALSE).to_u8(), 1);
675        assert_eq!((Choice::FALSE ^ Choice::TRUE).to_u8(), 1);
676        assert_eq!((Choice::TRUE ^ Choice::TRUE).to_u8(), 0);
677    }
678
679    #[test]
680    fn not() {
681        assert_eq!(Choice::FALSE.not().to_u8(), 1);
682        assert_eq!(Choice::TRUE.not().to_u8(), 0);
683    }
684
685    #[test]
686    fn from_i64_eq() {
687        assert!(Choice::from_i64_eq(0, 1).eq(Choice::FALSE).to_bool());
688        assert!(Choice::from_i64_eq(1, 1).eq(Choice::TRUE).to_bool());
689    }
690
691    #[test]
692    fn from_u8_eq() {
693        assert!(Choice::from_u8_eq(0, 1).eq(Choice::FALSE).to_bool());
694        assert!(Choice::from_u8_eq(1, 1).eq(Choice::TRUE).to_bool());
695    }
696
697    #[test]
698    fn from_u8_le() {
699        assert!(Choice::from_u8_le(0, 0).eq(Choice::TRUE).to_bool());
700        assert!(Choice::from_u8_le(1, 0).eq(Choice::FALSE).to_bool());
701        assert!(Choice::from_u8_le(1, 1).eq(Choice::TRUE).to_bool());
702        assert!(Choice::from_u8_le(1, 2).eq(Choice::TRUE).to_bool());
703    }
704
705    #[test]
706    fn from_u8_lsb() {
707        assert!(Choice::from_u8_lsb(0).eq(Choice::FALSE).to_bool());
708        assert!(Choice::from_u8_lsb(1).eq(Choice::TRUE).to_bool());
709        assert!(Choice::from_u8_lsb(2).eq(Choice::FALSE).to_bool());
710        assert!(Choice::from_u8_lsb(3).eq(Choice::TRUE).to_bool());
711    }
712
713    #[test]
714    fn from_u8_lt() {
715        assert!(Choice::from_u8_lt(0, 0).eq(Choice::FALSE).to_bool());
716        assert!(Choice::from_u8_lt(1, 0).eq(Choice::FALSE).to_bool());
717        assert!(Choice::from_u8_lt(1, 1).eq(Choice::FALSE).to_bool());
718        assert!(Choice::from_u8_lt(1, 2).eq(Choice::TRUE).to_bool());
719    }
720
721    #[test]
722    fn from_u8_nz() {
723        assert!(Choice::from_u8_nz(0).eq(Choice::FALSE).to_bool());
724        assert!(Choice::from_u8_nz(1).eq(Choice::TRUE).to_bool());
725        assert!(Choice::from_u8_nz(2).eq(Choice::TRUE).to_bool());
726    }
727
728    #[test]
729    fn from_u16_eq() {
730        assert!(Choice::from_u16_eq(0, 1).eq(Choice::FALSE).to_bool());
731        assert!(Choice::from_u16_eq(1, 1).eq(Choice::TRUE).to_bool());
732    }
733
734    #[test]
735    fn from_u16_le() {
736        assert!(Choice::from_u16_le(0, 0).eq(Choice::TRUE).to_bool());
737        assert!(Choice::from_u16_le(1, 0).eq(Choice::FALSE).to_bool());
738        assert!(Choice::from_u16_le(1, 1).eq(Choice::TRUE).to_bool());
739        assert!(Choice::from_u16_le(1, 2).eq(Choice::TRUE).to_bool());
740    }
741
742    #[test]
743    fn from_u16_lsb() {
744        assert!(Choice::from_u16_lsb(0).eq(Choice::FALSE).to_bool());
745        assert!(Choice::from_u16_lsb(1).eq(Choice::TRUE).to_bool());
746        assert!(Choice::from_u16_lsb(2).eq(Choice::FALSE).to_bool());
747        assert!(Choice::from_u16_lsb(3).eq(Choice::TRUE).to_bool());
748    }
749
750    #[test]
751    fn from_u16_lt() {
752        assert!(Choice::from_u16_lt(0, 0).eq(Choice::FALSE).to_bool());
753        assert!(Choice::from_u16_lt(1, 0).eq(Choice::FALSE).to_bool());
754        assert!(Choice::from_u16_lt(1, 1).eq(Choice::FALSE).to_bool());
755        assert!(Choice::from_u16_lt(1, 2).eq(Choice::TRUE).to_bool());
756    }
757
758    #[test]
759    fn from_u16_nz() {
760        assert!(Choice::from_u16_nz(0).eq(Choice::FALSE).to_bool());
761        assert!(Choice::from_u16_nz(1).eq(Choice::TRUE).to_bool());
762        assert!(Choice::from_u16_nz(2).eq(Choice::TRUE).to_bool());
763    }
764
765    #[test]
766    fn from_u32_eq() {
767        assert!(Choice::from_u32_eq(0, 1).eq(Choice::FALSE).to_bool());
768        assert!(Choice::from_u32_eq(1, 1).eq(Choice::TRUE).to_bool());
769    }
770
771    #[test]
772    fn from_u32_le() {
773        assert!(Choice::from_u32_le(0, 0).eq(Choice::TRUE).to_bool());
774        assert!(Choice::from_u32_le(1, 0).eq(Choice::FALSE).to_bool());
775        assert!(Choice::from_u32_le(1, 1).eq(Choice::TRUE).to_bool());
776        assert!(Choice::from_u32_le(1, 2).eq(Choice::TRUE).to_bool());
777    }
778
779    #[test]
780    fn from_u32_lsb() {
781        assert!(Choice::from_u32_lsb(0).eq(Choice::FALSE).to_bool());
782        assert!(Choice::from_u32_lsb(1).eq(Choice::TRUE).to_bool());
783        assert!(Choice::from_u32_lsb(2).eq(Choice::FALSE).to_bool());
784        assert!(Choice::from_u32_lsb(3).eq(Choice::TRUE).to_bool());
785    }
786
787    #[test]
788    fn from_u32_lt() {
789        assert!(Choice::from_u32_lt(0, 0).eq(Choice::FALSE).to_bool());
790        assert!(Choice::from_u32_lt(1, 0).eq(Choice::FALSE).to_bool());
791        assert!(Choice::from_u32_lt(1, 1).eq(Choice::FALSE).to_bool());
792        assert!(Choice::from_u32_lt(1, 2).eq(Choice::TRUE).to_bool());
793    }
794
795    #[test]
796    fn from_u32_nz() {
797        assert!(Choice::from_u32_nz(0).eq(Choice::FALSE).to_bool());
798        assert!(Choice::from_u32_nz(1).eq(Choice::TRUE).to_bool());
799        assert!(Choice::from_u32_nz(2).eq(Choice::TRUE).to_bool());
800    }
801
802    #[test]
803    fn from_u64_eq() {
804        assert!(Choice::from_u64_eq(0, 1).eq(Choice::FALSE).to_bool());
805        assert!(Choice::from_u64_eq(1, 1).eq(Choice::TRUE).to_bool());
806    }
807
808    #[test]
809    fn from_u64_le() {
810        assert!(Choice::from_u64_le(0, 0).eq(Choice::TRUE).to_bool());
811        assert!(Choice::from_u64_le(1, 0).eq(Choice::FALSE).to_bool());
812        assert!(Choice::from_u64_le(1, 1).eq(Choice::TRUE).to_bool());
813        assert!(Choice::from_u64_le(1, 2).eq(Choice::TRUE).to_bool());
814    }
815
816    #[test]
817    fn from_u64_lsb() {
818        assert!(Choice::from_u64_lsb(0).eq(Choice::FALSE).to_bool());
819        assert!(Choice::from_u64_lsb(1).eq(Choice::TRUE).to_bool());
820    }
821
822    #[test]
823    fn from_u64_lt() {
824        assert!(Choice::from_u64_lt(0, 0).eq(Choice::FALSE).to_bool());
825        assert!(Choice::from_u64_lt(1, 0).eq(Choice::FALSE).to_bool());
826        assert!(Choice::from_u64_lt(1, 1).eq(Choice::FALSE).to_bool());
827        assert!(Choice::from_u64_lt(1, 2).eq(Choice::TRUE).to_bool());
828    }
829
830    #[test]
831    fn from_u64_nz() {
832        assert!(Choice::from_u64_nz(0).eq(Choice::FALSE).to_bool());
833        assert!(Choice::from_u64_nz(1).eq(Choice::TRUE).to_bool());
834        assert!(Choice::from_u64_nz(2).eq(Choice::TRUE).to_bool());
835    }
836
837    #[test]
838    fn from_u128_eq() {
839        assert!(Choice::from_u128_eq(0, 1).eq(Choice::FALSE).to_bool());
840        assert!(Choice::from_u128_eq(1, 1).eq(Choice::TRUE).to_bool());
841    }
842
843    #[test]
844    fn from_u128_le() {
845        assert!(Choice::from_u128_le(0, 0).eq(Choice::TRUE).to_bool());
846        assert!(Choice::from_u128_le(1, 0).eq(Choice::FALSE).to_bool());
847        assert!(Choice::from_u128_le(1, 1).eq(Choice::TRUE).to_bool());
848        assert!(Choice::from_u128_le(1, 2).eq(Choice::TRUE).to_bool());
849    }
850
851    #[test]
852    fn from_u128_lsb() {
853        assert!(Choice::from_u128_lsb(0).eq(Choice::FALSE).to_bool());
854        assert!(Choice::from_u128_lsb(1).eq(Choice::TRUE).to_bool());
855    }
856
857    #[test]
858    fn from_u128_lt() {
859        assert!(Choice::from_u128_lt(0, 0).eq(Choice::FALSE).to_bool());
860        assert!(Choice::from_u128_lt(1, 0).eq(Choice::FALSE).to_bool());
861        assert!(Choice::from_u128_lt(1, 1).eq(Choice::FALSE).to_bool());
862        assert!(Choice::from_u128_lt(1, 2).eq(Choice::TRUE).to_bool());
863    }
864
865    #[test]
866    fn from_u128_nz() {
867        assert!(Choice::from_u128_nz(0).eq(Choice::FALSE).to_bool());
868        assert!(Choice::from_u128_nz(1).eq(Choice::TRUE).to_bool());
869        assert!(Choice::from_u128_nz(2).eq(Choice::TRUE).to_bool());
870    }
871
872    #[test]
873    fn select_i64() {
874        let a: i64 = 1;
875        let b: i64 = 2;
876        assert_eq!(Choice::TRUE.select_i64(a, b), b);
877        assert_eq!(Choice::FALSE.select_i64(a, b), a);
878    }
879
880    #[test]
881    fn select_u8() {
882        let a: u8 = 1;
883        let b: u8 = 2;
884        assert_eq!(Choice::TRUE.select_u8(a, b), b);
885        assert_eq!(Choice::FALSE.select_u8(a, b), a);
886    }
887
888    #[test]
889    fn select_u16() {
890        let a: u16 = 1;
891        let b: u16 = 2;
892        assert_eq!(Choice::TRUE.select_u16(a, b), b);
893        assert_eq!(Choice::FALSE.select_u16(a, b), a);
894    }
895
896    #[test]
897    fn select_u32() {
898        let a: u32 = 1;
899        let b: u32 = 2;
900        assert_eq!(Choice::TRUE.select_u32(a, b), b);
901        assert_eq!(Choice::FALSE.select_u32(a, b), a);
902    }
903
904    #[test]
905    fn select_u64() {
906        let a: u64 = 1;
907        let b: u64 = 2;
908        assert_eq!(Choice::TRUE.select_u64(a, b), b);
909        assert_eq!(Choice::FALSE.select_u64(a, b), a);
910    }
911
912    #[test]
913    fn select_u128() {
914        let a: u128 = 1;
915        let b: u128 = 2;
916        assert_eq!(Choice::TRUE.select_u128(a, b), b);
917        assert_eq!(Choice::FALSE.select_u128(a, b), a);
918    }
919
920    #[test]
921    fn to_bool() {
922        assert!(!Choice::FALSE.to_bool());
923        assert!(Choice::TRUE.to_bool());
924    }
925
926    #[test]
927    fn to_u8() {
928        assert_eq!(Choice::FALSE.to_u8(), 0);
929        assert_eq!(Choice::TRUE.to_u8(), 1);
930    }
931
932    #[test]
933    fn to_u8_mask() {
934        assert_eq!(Choice::FALSE.to_u8_mask(), 0);
935        assert_eq!(Choice::TRUE.to_u8_mask(), u8::MAX);
936    }
937
938    #[test]
939    fn to_u16_mask() {
940        assert_eq!(Choice::FALSE.to_u16_mask(), 0);
941        assert_eq!(Choice::TRUE.to_u16_mask(), u16::MAX);
942    }
943
944    #[test]
945    fn to_u32_mask() {
946        assert_eq!(Choice::FALSE.to_u32_mask(), 0);
947        assert_eq!(Choice::TRUE.to_u32_mask(), u32::MAX);
948    }
949
950    #[test]
951    fn to_u64_mask() {
952        assert_eq!(Choice::FALSE.to_u64_mask(), 0);
953        assert_eq!(Choice::TRUE.to_u64_mask(), u64::MAX);
954    }
955
956    #[test]
957    fn to_u128_mask() {
958        assert_eq!(Choice::FALSE.to_u128_mask(), 0);
959        assert_eq!(Choice::TRUE.to_u128_mask(), u128::MAX);
960    }
961}