diff --git a/ctutils/src/lib.rs b/ctutils/src/lib.rs index 8170e40c..3c11a82a 100644 --- a/ctutils/src/lib.rs +++ b/ctutils/src/lib.rs @@ -110,5 +110,5 @@ pub use traits::{ ct_lookup::CtLookup, ct_lt::CtLt, ct_neg::CtNeg, - ct_select::{CtSelect, CtSelectArray}, + ct_select::{CtSelect, CtSelectArray, CtSelectUsingCtAssign}, }; diff --git a/ctutils/src/traits/ct_assign.rs b/ctutils/src/traits/ct_assign.rs index 96f14e62..d315c476 100644 --- a/ctutils/src/traits/ct_assign.rs +++ b/ctutils/src/traits/ct_assign.rs @@ -95,10 +95,6 @@ impl CtAssignSlice for isize {} impl CtAssignSlice for usize {} /// Impl `CtAssign` using the `CtSelect` trait. -/// -/// In cases where `CtSelect` is more straightforward to implement, but you want to use a provided -/// implementation of `CtAssign` based on it, you can use this macro to write it for you. -#[macro_export] macro_rules! impl_ct_assign_with_ct_select { ( $($ty:ty),+ ) => { $( diff --git a/ctutils/src/traits/ct_select.rs b/ctutils/src/traits/ct_select.rs index 55b2e045..46375683 100644 --- a/ctutils/src/traits/ct_select.rs +++ b/ctutils/src/traits/ct_select.rs @@ -10,10 +10,10 @@ use core::{ #[cfg(feature = "subtle")] use crate::CtOption; #[cfg(feature = "alloc")] -use alloc::{boxed::Box, vec::Vec}; - -#[cfg(doc)] -use crate::CtAssignSlice; +use { + crate::CtAssignSlice, + alloc::{boxed::Box, vec::Vec}, +}; /// Constant-time selection: choose between two values based on a given [`Choice`]. /// @@ -79,26 +79,22 @@ where } } -/// Impl `CtSelect` using the `CtAssign` trait. -/// -/// In cases where `CtAssign` is more straightforward to implement, but you want to use a provided -/// implementation of `CtSelect` based on it, you can use this macro to write it for you. -/// -/// Requires the provided type(s) impl `Clone`. -#[macro_export] +/// Marker trait which enables a blanket impl of [`CtSelect`] for types which also impl +/// [`Clone`] + [`CtAssign`]. +pub trait CtSelectUsingCtAssign: Clone + CtAssign {} + +impl CtSelect for T { + #[inline] + fn ct_select(&self, other: &Self, choice: Choice) -> Self { + let mut ret = self.clone(); + ret.ct_assign(other, choice); + ret + } +} + +/// Macro to write impls of `CtSelectUsingCtAssign`. macro_rules! impl_ct_select_with_ct_assign { - ( $($ty:ty),+ ) => { - $( - impl CtSelect for $ty { - #[inline] - fn ct_select(&self, other: &Self, choice: Choice) -> Self { - let mut ret = self.clone(); - ret.ct_assign(other, choice); - ret - } - } - )+ - }; + ( $($ty:ty),+ ) => { $(impl CtSelectUsingCtAssign for $ty {})+ }; } impl_ct_select_with_ct_assign!( @@ -159,43 +155,18 @@ impl CtSelect for cmp::Ordering { } #[cfg(feature = "alloc")] -impl CtSelect for Box -where - T: CtSelect, -{ - #[inline] - fn ct_select(&self, other: &Self, choice: Choice) -> Self { - Box::new(T::ct_select(&**self, &**other, choice)) - } -} +impl CtSelectUsingCtAssign for Box {} #[cfg(feature = "alloc")] -impl CtSelect for Box<[T]> +impl CtSelectUsingCtAssign for Box<[T]> where T: Clone, [T]: CtAssign, { - #[inline] - fn ct_select(&self, other: &Self, choice: Choice) -> Self { - let mut ret = self.clone(); - ret.ct_assign(other, choice); - ret - } } #[cfg(feature = "alloc")] -impl CtSelect for Vec -where - T: Clone, - [T]: CtAssign, -{ - #[inline] - fn ct_select(&self, other: &Self, choice: Choice) -> Self { - let mut ret = self.clone(); - ret.ct_assign(other, choice); - ret - } -} +impl CtSelectUsingCtAssign for Vec {} #[cfg(feature = "subtle")] impl CtSelect for subtle::Choice {