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