1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
pub(crate) fn lookup<T, F>(array: &[T], matches: F) -> Option<&T>
where
F: Fn(&T) -> Choice,
{
let mut idx: u64 = 0;
let mut found: Choice = 0.into();
for (i, x) in array.iter().enumerate() {
let equal = matches(x);
idx.conditional_assign(&(i as u64), equal);
found.conditional_assign(&equal, equal);
}
if found.into() {
Some(&array[idx as usize])
} else {
None
}
}
pub(crate) fn bool_to_choice(v: bool) -> Choice {
Choice::from(u8::from(v))
}
pub(crate) fn bytes_eq(a: &[u8], b: &[u8]) -> bool {
let choice = a.ct_eq(b);
choice.unwrap_u8() == 1
}
#[cfg(test)]
mod test {
#![allow(clippy::unwrap_used)]
#[test]
fn test_bytes_eq() {
use super::bytes_eq;
assert!(bytes_eq(&b"123"[..], &b"1234"[..3]));
assert!(!bytes_eq(&b"123"[..], &b"1234"[..]));
assert!(bytes_eq(&b"45"[..], &b"45"[..]));
assert!(!bytes_eq(&b"hi"[..], &b"45"[..]));
assert!(bytes_eq(&b""[..], &b""[..]));
}
#[test]
fn test_lookup() {
use super::lookup;
use subtle::ConstantTimeEq;
let items = vec![
"One".to_string(),
"word".to_string(),
"of".to_string(),
"every".to_string(),
"length".to_string(),
];
let of_word = lookup(&items[..], |i| i.len().ct_eq(&2));
let every_word = lookup(&items[..], |i| i.len().ct_eq(&5));
let no_word = lookup(&items[..], |i| i.len().ct_eq(&99));
assert_eq!(of_word.unwrap(), "of");
assert_eq!(every_word.unwrap(), "every");
assert_eq!(no_word, None);
}
}