diff --git a/ctutils/src/choice.rs b/ctutils/src/choice.rs index 494c2d45..4c6b0104 100644 --- a/ctutils/src/choice.rs +++ b/ctutils/src/choice.rs @@ -275,6 +275,24 @@ impl Choice { self.select_u64(a as u64, b as u64) as i64 } + /// `const fn` helper: return `b` if `self` is [`Choice::TRUE`], otherwise return `a`. + /// + /// Only use this instead of the [`CtSelect`] trait in the event you're in a `const fn` context + /// and can't use the trait. The former will provide better constant-time assurances. + #[inline] + pub const fn select_u8(self, a: u8, b: u8) -> u8 { + a ^ (self.to_u8_mask() & (a ^ b)) + } + + /// `const fn` helper: return `b` if `self` is [`Choice::TRUE`], otherwise return `a`. + /// + /// Only use this instead of the [`CtSelect`] trait in the event you're in a `const fn` context + /// and can't use the trait. The former will provide better constant-time assurances. + #[inline] + pub const fn select_u16(self, a: u16, b: u16) -> u16 { + a ^ (self.to_u16_mask() & (a ^ b)) + } + /// `const fn` helper: return `b` if `self` is [`Choice::TRUE`], otherwise return `a`. /// /// Only use this instead of the [`CtSelect`] trait in the event you're in a `const fn` context @@ -802,6 +820,22 @@ mod tests { assert_eq!(Choice::FALSE.select_i64(a, b), a); } + #[test] + fn select_u8() { + let a: u8 = 1; + let b: u8 = 2; + assert_eq!(Choice::TRUE.select_u8(a, b), b); + assert_eq!(Choice::FALSE.select_u8(a, b), a); + } + + #[test] + fn select_u16() { + let a: u16 = 1; + let b: u16 = 2; + assert_eq!(Choice::TRUE.select_u16(a, b), b); + assert_eq!(Choice::FALSE.select_u16(a, b), a); + } + #[test] fn select_u32() { let a: u32 = 1;