vitaminc_protected/protected/
mod.rs1use super::Controlled;
2use crate::private::ControlledPrivate;
3use zeroize::{Zeroize, ZeroizeOnDrop};
4
5#[derive(Zeroize)]
8pub struct Protected<T>(pub(crate) T);
9
10opaque_debug::implement!(Protected<T>);
11
12impl<T> Protected<T> {
13 pub const fn new(x: T) -> Self
15 where
16 T: Zeroize,
17 {
18 Self(x)
19 }
20}
21
22impl<T> Protected<Protected<T>> {
23 #[inline]
24 pub fn flatten(self) -> Protected<T> {
37 self.0
38 }
39}
40
41impl<T> Protected<Option<T>> {
42 #[inline]
43 pub fn transpose(self) -> Option<Protected<T>> {
53 self.0.map(Protected)
54 }
55}
56
57impl<T: Zeroize> ZeroizeOnDrop for Protected<T> {}
58
59impl<T> ControlledPrivate for Protected<T> {}
60
61impl<T> Controlled for Protected<T>
62where
63 T: Zeroize,
64{
65 fn risky_unwrap(self) -> Self::Inner {
66 self.0
67 }
68
69 type Inner = T;
70
71 fn init_from_inner(x: Self::Inner) -> Self {
72 Self(x)
73 }
74
75 fn risky_ref(&self) -> &T {
76 &self.0
77 }
78
79 fn inner_mut(&mut self) -> &mut Self::Inner {
80 &mut self.0
81 }
82}
83
84impl<T> Copy for Protected<T> where T: Copy {}
85
86impl<T> Clone for Protected<T>
87where
88 T: Clone,
89{
90 fn clone(&self) -> Self {
91 Self(self.0.clone())
92 }
93}
94
95impl<T, A> Extend<A> for Protected<T>
96where
97 T: Extend<A>,
98{
99 fn extend<I>(&mut self, iter: I)
100 where
101 I: IntoIterator<Item = A>,
102 {
103 self.0.extend(iter);
104 }
105}
106
107#[cfg(feature = "arbitrary")]
108impl<T> quickcheck::Arbitrary for Protected<T>
109where
110 T: quickcheck::Arbitrary + Zeroize,
111{
112 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
113 let inner = T::arbitrary(g);
114 Self::new(inner)
115 }
116}
117
118pub fn flatten_array<const N: usize, T>(array: [Protected<T>; N]) -> Protected<[T; N]>
133where
134 T: Zeroize + Default + Copy, {
136 let mut out: [T; N] = [Default::default(); N];
137 array.iter().enumerate().for_each(|(i, x)| {
138 out[i] = x.risky_unwrap();
139 });
140 Protected::new(out)
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn test_new_array() {
149 let x = Protected::new([0u8; 32]);
150 assert_eq!(x.0, [0u8; 32]);
151 }
152
153 #[test]
154 fn test_opaque_debug() {
155 let x = Protected::new([0u8; 32]);
156 assert_eq!(format!("{x:?}"), "Protected<[u8; 32]> { ... }");
157 }
158
159 #[test]
160 fn test_flatten() {
161 let x = Protected::new(Protected::new([0u8; 32]));
162 let y = x.flatten();
163 assert_eq!(y.risky_unwrap(), [0u8; 32]);
164 }
165
166 #[test]
167 fn test_flatten_array() {
168 let x = Protected::new(1);
169 let y = Protected::new(2);
170 let z = Protected::new(3);
171 let array: [Protected<u8>; 3] = [x, y, z];
172 let flattened = flatten_array(array);
173 assert!(matches!(flattened, Protected(_)));
174 assert_eq!(flattened.risky_unwrap(), [1, 2, 3]);
175 }
176}