ctutils/traits/
ct_lookup.rs1use crate::{CtAssign, CtEq, CtOption};
2use core::ops::AddAssign;
3
4#[cfg(doc)]
5use core::ops::Index;
6
7pub trait CtLookup<Idx> {
10 type Output: CtAssign;
12
13 #[must_use]
16 fn ct_lookup(&self, index: Idx) -> CtOption<Self::Output>;
17}
18
19impl<T, Idx> CtLookup<Idx> for [T]
20where
21 T: CtAssign + Default,
22 Idx: AddAssign + CtEq + Default + From<u8>,
23{
24 type Output = T;
25
26 #[inline]
27 fn ct_lookup(&self, index: Idx) -> CtOption<T> {
28 let mut ret = CtOption::none();
29 let mut i = Idx::default();
30
31 for item in self {
32 ret.insert_if(item, i.ct_eq(&index));
33
34 i += Idx::from(1u8);
36 }
37
38 ret
39 }
40}
41
42impl<T, Idx, const N: usize> CtLookup<Idx> for [T; N]
43where
44 T: CtAssign + Default,
45 Idx: AddAssign + CtEq + Default + From<u8>,
46{
47 type Output = T;
48
49 #[inline]
50 fn ct_lookup(&self, index: Idx) -> CtOption<T> {
51 self.as_slice().ct_lookup(index)
52 }
53}
54
55#[cfg(feature = "alloc")]
56mod alloc {
57 use super::{AddAssign, CtAssign, CtEq, CtLookup, CtOption};
58 use ::alloc::{boxed::Box, vec::Vec};
59
60 impl<T, Idx> CtLookup<Idx> for Box<[T]>
61 where
62 T: CtAssign + Default,
63 Idx: AddAssign + CtEq + Default + From<u8>,
64 {
65 type Output = T;
66
67 #[inline]
68 fn ct_lookup(&self, index: Idx) -> CtOption<T> {
69 (**self).ct_lookup(index)
70 }
71 }
72
73 impl<T, Idx> CtLookup<Idx> for Vec<T>
74 where
75 T: CtAssign + Default,
76 Idx: AddAssign + CtEq + Default + From<u8>,
77 {
78 type Output = T;
79
80 #[inline]
81 fn ct_lookup(&self, index: Idx) -> CtOption<T> {
82 self.as_slice().ct_lookup(index)
83 }
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 mod array {
90 use crate::CtLookup;
91
92 const EXAMPLE: [u8; 3] = [1, 2, 3];
93
94 #[test]
95 fn ct_lookup_u32() {
96 assert_eq!(EXAMPLE.ct_lookup(0u32).unwrap(), 1);
97 assert_eq!(EXAMPLE.ct_lookup(1u32).unwrap(), 2);
98 assert_eq!(EXAMPLE.ct_lookup(2u32).unwrap(), 3);
99 assert!(EXAMPLE.ct_lookup(3u32).is_none().to_bool());
100 assert!(EXAMPLE.ct_lookup(4u32).is_none().to_bool());
101 }
102
103 #[test]
104 fn ct_lookup_usize() {
105 assert_eq!(EXAMPLE.ct_lookup(0usize).unwrap(), 1);
106 assert_eq!(EXAMPLE.ct_lookup(1usize).unwrap(), 2);
107 assert_eq!(EXAMPLE.ct_lookup(2usize).unwrap(), 3);
108 assert!(EXAMPLE.ct_lookup(3usize).is_none().to_bool());
109 assert!(EXAMPLE.ct_lookup(4usize).is_none().to_bool());
110 }
111 }
112
113 mod slice {
114 use crate::CtLookup;
115
116 const EXAMPLE: &[u8] = &[1, 2, 3];
117
118 #[test]
119 fn ct_lookup_u32() {
120 assert_eq!(EXAMPLE.ct_lookup(0u32).unwrap(), 1);
121 assert_eq!(EXAMPLE.ct_lookup(1u32).unwrap(), 2);
122 assert_eq!(EXAMPLE.ct_lookup(2u32).unwrap(), 3);
123 assert!(EXAMPLE.ct_lookup(3u32).is_none().to_bool());
124 assert!(EXAMPLE.ct_lookup(4u32).is_none().to_bool());
125 }
126
127 #[test]
128 fn ct_lookup_usize() {
129 assert_eq!(EXAMPLE.ct_lookup(0usize).unwrap(), 1);
130 assert_eq!(EXAMPLE.ct_lookup(1usize).unwrap(), 2);
131 assert_eq!(EXAMPLE.ct_lookup(2usize).unwrap(), 3);
132 assert!(EXAMPLE.ct_lookup(3usize).is_none().to_bool());
133 assert!(EXAMPLE.ct_lookup(4usize).is_none().to_bool());
134 }
135 }
136}