@@ -341,8 +341,8 @@ impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
341341 /// Since arrays coerce to slices, this function works with fixed-size arrays:
342342 ///
343343 /// ```
344- /// # use subtle::ConstantTimeEq;
345- /// #
344+ /// use subtle::ConstantTimeEq;
345+ ///
346346 /// let a: [u8; 8] = [0,1,2,3,4,5,6,7];
347347 /// let b: [u8; 8] = [0,1,2,3,0,1,2,3];
348348 ///
@@ -359,7 +359,7 @@ impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
359359 // Short-circuit on the *lengths* of the slices, not their
360360 // contents.
361361 if len != _rhs. len ( ) {
362- return Choice :: from ( 0 ) ;
362+ return Choice :: of_bool ( false ) ;
363363 }
364364
365365 let mut x = IteratedEq :: initiate ( ) ;
@@ -938,7 +938,7 @@ generate_unsigned_integer_greater!(u64, 64);
938938#[ cfg( feature = "i128" ) ]
939939generate_unsigned_integer_greater ! ( u128 , 128 ) ;
940940
941- impl < T : ConstantTimeGreater + ConstantTimeEq > ConstantTimeGreater for [ T ] {
941+ impl < T : ConstantTimeGreater > ConstantTimeGreater for [ T ] {
942942 /// Compare whether one slice of `ConstantTimeGreater` types is greater than another.
943943 ///
944944 /// # Note
@@ -953,8 +953,8 @@ impl<T: ConstantTimeGreater + ConstantTimeEq> ConstantTimeGreater for [T] {
953953 /// Since arrays coerce to slices, this function also works with fixed-size arrays:
954954 ///
955955 /// ```
956- /// # use subtle::ConstantTimeGreater;
957- /// #
956+ /// use subtle::ConstantTimeGreater;
957+ ///
958958 /// let a: [u8; 8] = [0,1,2,3,4,5,6,7];
959959 /// let b: [u8; 8] = [0,1,2,3,0,1,2,3];
960960 ///
@@ -973,10 +973,10 @@ impl<T: ConstantTimeGreater + ConstantTimeEq> ConstantTimeGreater for [T] {
973973 match len. cmp ( & _rhs. len ( ) ) {
974974 Ordering :: Equal => ( ) ,
975975 Ordering :: Less => {
976- return Choice :: from ( 0 ) ;
976+ return Choice :: of_bool ( false ) ;
977977 }
978978 Ordering :: Greater => {
979- return Choice :: from ( 1 ) ;
979+ return Choice :: of_bool ( true ) ;
980980 }
981981 }
982982
@@ -1099,3 +1099,54 @@ impl LexicographicIteratedLess {
10991099 * was_gt |= b. ct_lt ( & a) ;
11001100 }
11011101}
1102+
1103+ impl < T : ConstantTimeLess > ConstantTimeLess for [ T ] {
1104+ /// Compare whether one slice of `ConstantTimeLess` types is greater than another.
1105+ ///
1106+ /// # Note
1107+ ///
1108+ /// This function short-circuits if the lengths of the input slices are different. Otherwise,
1109+ /// it should execute in time independent of the slice contents. When the slice lengths differ,
1110+ /// this implementation applies the [shortlex] ordering scheme, which sorts shorter slices
1111+ /// before longer slices without checking the contents.
1112+ ///
1113+ /// [shortlex]: https://en.wikipedia.org/wiki/Shortlex_order
1114+ ///
1115+ /// Since arrays coerce to slices, this function also works with fixed-size arrays:
1116+ ///
1117+ /// ```
1118+ /// use subtle::ConstantTimeLess;
1119+ ///
1120+ /// let a: [u8; 8] = [0,1,2,3,0,1,2,3];
1121+ /// let b: [u8; 8] = [0,1,2,3,4,5,6,7];
1122+ ///
1123+ /// let a_lt_a = a.ct_lt(&a);
1124+ /// let a_lt_b = a.ct_lt(&b);
1125+ ///
1126+ /// assert_eq!(a_lt_a.unwrap_u8(), 0);
1127+ /// assert_eq!(a_lt_b.unwrap_u8(), 1);
1128+ /// ```
1129+ #[ inline]
1130+ fn ct_lt ( & self , _rhs : & [ T ] ) -> Choice {
1131+ let len = self . len ( ) ;
1132+
1133+ // Short-circuit on the *lengths* of the slices, not their contents. Here we apply shortlex
1134+ // ordering, sorting shorter slices before longer ones.
1135+ match len. cmp ( & _rhs. len ( ) ) {
1136+ Ordering :: Equal => ( ) ,
1137+ Ordering :: Less => {
1138+ return Choice :: of_bool ( true ) ;
1139+ }
1140+ Ordering :: Greater => {
1141+ return Choice :: of_bool ( false ) ;
1142+ }
1143+ }
1144+
1145+ let mut x = LexicographicIteratedLess :: initiate ( ) ;
1146+ for ( ai, bi) in self . iter ( ) . zip ( _rhs. iter ( ) ) {
1147+ x. apply_lt ( ai, bi) ;
1148+ }
1149+
1150+ x. extract_result ( )
1151+ }
1152+ }
0 commit comments