@@ -126,6 +126,7 @@ impl Choice {
126
126
///
127
127
/// This function only exists as an **escape hatch** for the rare case
128
128
/// where it's not possible to use one of the `subtle`-provided
129
+ /// where it's not possible to use one of the `subtle`-provided
129
130
/// trait impls.
130
131
///
131
132
/// **To convert a `Choice` to a `bool`, use the `From` implementation instead.**
@@ -383,14 +384,19 @@ impl ConstantTimeEq for cmp::Ordering {
383
384
}
384
385
}
385
386
387
+ /// Marker trait for types whose [`Clone`] impl operates in constant-time.
388
+ pub trait ConstantTimeClone : Clone { }
389
+
390
+ impl < T : Copy > ConstantTimeClone for T { }
391
+
386
392
/// A type which can be conditionally selected in constant time.
387
393
///
388
394
/// This trait also provides generic implementations of conditional
389
395
/// assignment and conditional swaps.
390
396
//
391
397
// #[inline] is specified on these function prototypes to signify that they
392
398
#[ allow( unused_attributes) ] // should be in the actual implementation
393
- pub trait ConditionallySelectable : Copy {
399
+ pub trait ConditionallySelectable : ConstantTimeClone {
394
400
/// Select `a` or `b` according to `choice`.
395
401
///
396
402
/// # Returns
@@ -467,7 +473,7 @@ pub trait ConditionallySelectable: Copy {
467
473
/// ```
468
474
#[ inline]
469
475
fn conditional_swap ( a : & mut Self , b : & mut Self , choice : Choice ) {
470
- let t: Self = * a ;
476
+ let t: Self = a . clone ( ) ;
471
477
a. conditional_assign ( & b, choice) ;
472
478
b. conditional_assign ( & t, choice) ;
473
479
}
@@ -575,7 +581,7 @@ impl ConditionallySelectable for Choice {
575
581
#[ cfg( feature = "const-generics" ) ]
576
582
impl < T , const N : usize > ConditionallySelectable for [ T ; N ]
577
583
where
578
- T : ConditionallySelectable ,
584
+ T : ConditionallySelectable + Copy ,
579
585
{
580
586
#[ inline]
581
587
fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self {
@@ -741,49 +747,34 @@ impl<T> CtOption<T> {
741
747
742
748
/// Returns a `None` value if the option is `None`, otherwise
743
749
/// returns a `CtOption` enclosing the value of the provided closure.
744
- /// The closure is given the enclosed value or, if the option is
745
- /// `None`, it is provided a dummy value computed using
746
- /// `Default::default()`.
750
+ /// The closure is given the enclosed value.
747
751
///
748
752
/// This operates in constant time, because the provided closure
749
753
/// is always called.
750
754
#[ inline]
751
755
pub fn map < U , F > ( self , f : F ) -> CtOption < U >
752
756
where
753
- T : Default + ConditionallySelectable ,
757
+ T : ConditionallySelectable ,
754
758
F : FnOnce ( T ) -> U ,
755
759
{
756
- CtOption :: new (
757
- f ( T :: conditional_select (
758
- & T :: default ( ) ,
759
- & self . value ,
760
- self . is_some ,
761
- ) ) ,
762
- self . is_some ,
763
- )
760
+ CtOption :: new ( f ( self . value ) , self . is_some )
764
761
}
765
762
766
763
/// Returns a `None` value if the option is `None`, otherwise
767
764
/// returns the result of the provided closure. The closure is
768
- /// given the enclosed value or, if the option is `None`, it
769
- /// is provided a dummy value computed using `Default::default()`.
765
+ /// given the enclosed value.
770
766
///
771
767
/// This operates in constant time, because the provided closure
772
768
/// is always called.
773
769
#[ inline]
774
770
pub fn and_then < U , F > ( self , f : F ) -> CtOption < U >
775
771
where
776
- T : Default + ConditionallySelectable ,
772
+ T : ConditionallySelectable ,
777
773
F : FnOnce ( T ) -> CtOption < U > ,
778
774
{
779
- let mut tmp = f ( T :: conditional_select (
780
- & T :: default ( ) ,
781
- & self . value ,
782
- self . is_some ,
783
- ) ) ;
784
- tmp. is_some &= self . is_some ;
785
-
786
- tmp
775
+ let mut ret = f ( self . value ) ;
776
+ ret. is_some &= self . is_some ;
777
+ ret
787
778
}
788
779
789
780
/// Returns `self` if it contains a value, and otherwise returns the result of
@@ -797,7 +788,10 @@ impl<T> CtOption<T> {
797
788
let is_none = self . is_none ( ) ;
798
789
let f = f ( ) ;
799
790
800
- Self :: conditional_select ( & self , & f, is_none)
791
+ CtOption :: new (
792
+ T :: conditional_select ( & self . value , & f. value , is_none) ,
793
+ Choice :: conditional_select ( & self . is_some , & f. is_some , is_none) ,
794
+ )
801
795
}
802
796
803
797
/// Convert the `CtOption<T>` wrapper into an `Option<T>`, depending on whether
@@ -817,7 +811,10 @@ impl<T> CtOption<T> {
817
811
}
818
812
}
819
813
820
- impl < T : ConditionallySelectable > ConditionallySelectable for CtOption < T > {
814
+ impl < T > ConditionallySelectable for CtOption < T >
815
+ where
816
+ T : ConditionallySelectable + Copy
817
+ {
821
818
fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self {
822
819
CtOption :: new (
823
820
T :: conditional_select ( & a. value , & b. value , choice) ,
0 commit comments