rostl_primitives/
traits.rs

1//! Traits for conditional move and swap operations.
2use crate::indexable::Indexable;
3use assume::assume;
4
5#[allow(missing_docs)]
6pub trait _Cmovbase {
7  fn cmov_base(&mut self, other: &Self, choice: bool);
8  fn cxchg_base(&mut self, other: &mut Self, choice: bool);
9}
10
11/// A trait for conditionally moving values with constant memory trace.
12///
13pub trait Cmov: Sized {
14  /// Conditionally move `other` into `self` based on `choice`.
15  /// @Oblivious
16  fn cmov(&mut self, other: &Self, choice: bool);
17  /// Conditionally exchange `other` and `self` based on `choice`.
18  /// @Oblivious
19  fn cxchg(&mut self, other: &mut Self, choice: bool);
20
21  /// Conditionally set `self` to either `val_false` or `val_true` based on `choice`.
22  /// @Oblivious
23  #[inline]
24  fn cset(&mut self, val_false: &Self, val_true: &Self, choice: bool) {
25    self.cmov(val_true, choice);
26    self.cmov(val_false, !choice);
27  }
28}
29
30/// A trait for conditionally swapping values with constant memory trace.
31///
32#[inline]
33pub fn cswap<T: Cmov + Copy>(first: &mut T, second: &mut T, choice: bool) {
34  let tmp = *first;
35  first.cmov(second, choice);
36  second.cmov(&tmp, choice);
37}
38
39/// Adds cswap for Indexables of cswap-able types.
40pub trait CswapIndex<T> {
41  /// Conditionally swap the elements at `i` and `j` based on `choice`.
42  /// @Oblivious
43  /// # Requirements
44  /// * `i < self.len()`
45  /// * `j < self.len()`
46  /// * `i != j || choice == false`
47  fn cswap(&mut self, i: usize, j: usize, choice: bool);
48}
49
50impl<T, C> CswapIndex<T> for C
51where
52  C: Indexable<T> + ?Sized,
53  T: Cmov + Copy,
54{
55  fn cswap(&mut self, i: usize, j: usize, choice: bool) {
56    assert!(i != j);
57    assume!(unsafe: i < self.len());
58    assume!(unsafe: j < self.len());
59    assume!(unsafe: i != j);
60    let mut left = self[i];
61    let mut right = self[j];
62    cswap(&mut left, &mut right, choice);
63    self[i] = left;
64    self[j] = right;
65  }
66}