Skip to content

Commit 6e30036

Browse files
authored
ctutils: add CtSelectUsingCtAssign (#1391)
Adds a marker trait bounded on `Clone + CtAssign` which writes a blanket impl of `CtSelect` by cloning `self` and then performing `CtAssign`. The blanket impl is used to replace all of the repeat occurrences in this crate alone, including the `impl_ct_select_with_ct_assign!` macro.
1 parent 8d776bd commit 6e30036

File tree

3 files changed

+23
-56
lines changed

3 files changed

+23
-56
lines changed

ctutils/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,5 @@ pub use traits::{
110110
ct_lookup::CtLookup,
111111
ct_lt::CtLt,
112112
ct_neg::CtNeg,
113-
ct_select::{CtSelect, CtSelectArray},
113+
ct_select::{CtSelect, CtSelectArray, CtSelectUsingCtAssign},
114114
};

ctutils/src/traits/ct_assign.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@ impl CtAssignSlice for isize {}
9595
impl CtAssignSlice for usize {}
9696

9797
/// Impl `CtAssign` using the `CtSelect` trait.
98-
///
99-
/// In cases where `CtSelect` is more straightforward to implement, but you want to use a provided
100-
/// implementation of `CtAssign` based on it, you can use this macro to write it for you.
101-
#[macro_export]
10298
macro_rules! impl_ct_assign_with_ct_select {
10399
( $($ty:ty),+ ) => {
104100
$(

ctutils/src/traits/ct_select.rs

Lines changed: 22 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ use core::{
1010
#[cfg(feature = "subtle")]
1111
use crate::CtOption;
1212
#[cfg(feature = "alloc")]
13-
use alloc::{boxed::Box, vec::Vec};
14-
15-
#[cfg(doc)]
16-
use crate::CtAssignSlice;
13+
use {
14+
crate::CtAssignSlice,
15+
alloc::{boxed::Box, vec::Vec},
16+
};
1717

1818
/// Constant-time selection: choose between two values based on a given [`Choice`].
1919
///
@@ -79,26 +79,22 @@ where
7979
}
8080
}
8181

82-
/// Impl `CtSelect` using the `CtAssign` trait.
83-
///
84-
/// In cases where `CtAssign` is more straightforward to implement, but you want to use a provided
85-
/// implementation of `CtSelect` based on it, you can use this macro to write it for you.
86-
///
87-
/// Requires the provided type(s) impl `Clone`.
88-
#[macro_export]
82+
/// Marker trait which enables a blanket impl of [`CtSelect`] for types which also impl
83+
/// [`Clone`] + [`CtAssign`].
84+
pub trait CtSelectUsingCtAssign: Clone + CtAssign {}
85+
86+
impl<T: CtSelectUsingCtAssign> CtSelect for T {
87+
#[inline]
88+
fn ct_select(&self, other: &Self, choice: Choice) -> Self {
89+
let mut ret = self.clone();
90+
ret.ct_assign(other, choice);
91+
ret
92+
}
93+
}
94+
95+
/// Macro to write impls of `CtSelectUsingCtAssign`.
8996
macro_rules! impl_ct_select_with_ct_assign {
90-
( $($ty:ty),+ ) => {
91-
$(
92-
impl CtSelect for $ty {
93-
#[inline]
94-
fn ct_select(&self, other: &Self, choice: Choice) -> Self {
95-
let mut ret = self.clone();
96-
ret.ct_assign(other, choice);
97-
ret
98-
}
99-
}
100-
)+
101-
};
97+
( $($ty:ty),+ ) => { $(impl CtSelectUsingCtAssign for $ty {})+ };
10298
}
10399

104100
impl_ct_select_with_ct_assign!(
@@ -159,43 +155,18 @@ impl CtSelect for cmp::Ordering {
159155
}
160156

161157
#[cfg(feature = "alloc")]
162-
impl<T> CtSelect for Box<T>
163-
where
164-
T: CtSelect,
165-
{
166-
#[inline]
167-
fn ct_select(&self, other: &Self, choice: Choice) -> Self {
168-
Box::new(T::ct_select(&**self, &**other, choice))
169-
}
170-
}
158+
impl<T: Clone + CtAssign> CtSelectUsingCtAssign for Box<T> {}
171159

172160
#[cfg(feature = "alloc")]
173-
impl<T> CtSelect for Box<[T]>
161+
impl<T> CtSelectUsingCtAssign for Box<[T]>
174162
where
175163
T: Clone,
176164
[T]: CtAssign,
177165
{
178-
#[inline]
179-
fn ct_select(&self, other: &Self, choice: Choice) -> Self {
180-
let mut ret = self.clone();
181-
ret.ct_assign(other, choice);
182-
ret
183-
}
184166
}
185167

186168
#[cfg(feature = "alloc")]
187-
impl<T> CtSelect for Vec<T>
188-
where
189-
T: Clone,
190-
[T]: CtAssign,
191-
{
192-
#[inline]
193-
fn ct_select(&self, other: &Self, choice: Choice) -> Self {
194-
let mut ret = self.clone();
195-
ret.ct_assign(other, choice);
196-
ret
197-
}
198-
}
169+
impl<T: Clone + CtAssignSlice> CtSelectUsingCtAssign for Vec<T> {}
199170

200171
#[cfg(feature = "subtle")]
201172
impl CtSelect for subtle::Choice {

0 commit comments

Comments
 (0)