1#[cfg(feature = "alloc")]
2extern crate alloc;
3use alloc::boxed::Box;
4
5#[cfg(feature = "rand")]
6use rand::{rngs::OsRng, TryRngCore};
7
8#[cfg(feature = "encoding-base64")]
9use crate::traits::decoding::base64_url::FromBase64UrlStr;
10#[cfg(feature = "encoding-bech32")]
11use crate::traits::decoding::bech32::FromBech32Str;
12#[cfg(feature = "encoding-bech32m")]
13use crate::traits::decoding::bech32m::FromBech32mStr;
14#[cfg(feature = "encoding-hex")]
15use crate::traits::decoding::hex::FromHexStr;
16
17pub struct Dynamic<T: ?Sized> {
28 inner: Box<T>,
29}
30
31impl<T: ?Sized> Dynamic<T> {
32 #[inline(always)]
36 pub fn new<U>(value: U) -> Self
37 where
38 U: Into<Box<T>>,
39 {
40 let inner = value.into();
41 Self { inner }
42 }
43}
44
45impl Dynamic<String> {}
47
48impl<T> Dynamic<Vec<T>> {}
49
50impl<T: ?Sized> From<Box<T>> for Dynamic<T> {
52 #[inline(always)]
54 fn from(boxed: Box<T>) -> Self {
55 Self { inner: boxed }
56 }
57}
58
59impl From<&[u8]> for Dynamic<Vec<u8>> {
60 #[inline(always)]
62 fn from(slice: &[u8]) -> Self {
63 Self::new(slice.to_vec())
64 }
65}
66
67impl From<&str> for Dynamic<String> {
68 #[inline(always)]
70 fn from(input: &str) -> Self {
71 Self::new(input.to_string())
72 }
73}
74
75impl<T: 'static> From<T> for Dynamic<T> {
76 #[inline(always)]
78 fn from(value: T) -> Self {
79 Self {
80 inner: Box::new(value),
81 }
82 }
83}
84
85impl crate::ExposeSecret for Dynamic<String> {
86 type Inner = String;
87 #[inline(always)]
88 fn with_secret<F, R>(&self, f: F) -> R
89 where
90 F: FnOnce(&String) -> R,
91 {
92 f(&self.inner)
93 }
94 #[inline(always)]
95 fn expose_secret(&self) -> &String {
96 &self.inner
97 }
98 #[inline(always)]
99 fn len(&self) -> usize {
100 self.inner.len()
101 }
102}
103
104impl<T> crate::ExposeSecret for Dynamic<Vec<T>> {
105 type Inner = Vec<T>;
106 #[inline(always)]
107 fn with_secret<F, R>(&self, f: F) -> R
108 where
109 F: FnOnce(&Vec<T>) -> R,
110 {
111 f(&self.inner)
112 }
113 #[inline(always)]
114 fn expose_secret(&self) -> &Vec<T> {
115 &self.inner
116 }
117 #[inline(always)]
118 fn len(&self) -> usize {
119 self.inner.len() * core::mem::size_of::<T>()
120 }
121}
122
123impl crate::ExposeSecretMut for Dynamic<String> {
124 #[inline(always)]
125 fn with_secret_mut<F, R>(&mut self, f: F) -> R
126 where
127 F: FnOnce(&mut String) -> R,
128 {
129 f(&mut self.inner)
130 }
131 #[inline(always)]
132 fn expose_secret_mut(&mut self) -> &mut String {
133 &mut self.inner
134 }
135}
136
137impl<T> crate::ExposeSecretMut for Dynamic<Vec<T>> {
138 #[inline(always)]
139 fn with_secret_mut<F, R>(&mut self, f: F) -> R
140 where
141 F: FnOnce(&mut Vec<T>) -> R,
142 {
143 f(&mut self.inner)
144 }
145 #[inline(always)]
146 fn expose_secret_mut(&mut self) -> &mut Vec<T> {
147 &mut self.inner
148 }
149}
150
151#[cfg(feature = "rand")]
153impl Dynamic<alloc::vec::Vec<u8>> {
154 #[inline]
159 pub fn from_random(len: usize) -> Self {
160 let mut bytes = vec![0u8; len];
161 OsRng
162 .try_fill_bytes(&mut bytes)
163 .expect("OsRng failure is a program error");
164 Self::from(bytes)
165 }
166}
167
168#[cfg(feature = "encoding-hex")]
170impl Dynamic<alloc::vec::Vec<u8>> {
171 pub fn try_from_hex(s: &str) -> Result<Self, crate::error::HexError> {
183 let bytes = s.try_from_hex()?;
184 Ok(Self::new(bytes))
185 }
186}
187
188#[cfg(feature = "encoding-base64")]
189impl Dynamic<alloc::vec::Vec<u8>> {
190 pub fn try_from_base64url(s: &str) -> Result<Self, crate::error::Base64Error> {
202 let bytes = s.try_from_base64url()?;
203 Ok(Self::new(bytes))
204 }
205}
206
207#[cfg(feature = "encoding-bech32")]
208impl Dynamic<alloc::vec::Vec<u8>> {
209 pub fn try_from_bech32(s: &str) -> Result<Self, crate::error::Bech32Error> {
222 let (_hrp, bytes) = s.try_from_bech32()?;
223 Ok(Self::new(bytes))
224 }
225}
226
227#[cfg(feature = "encoding-bech32m")]
228impl Dynamic<alloc::vec::Vec<u8>> {
229 pub fn try_from_bech32m(s: &str) -> Result<Self, crate::error::Bech32Error> {
242 let (_hrp, bytes) = s.try_from_bech32m()?;
243 Ok(Self::new(bytes))
244 }
245}
246
247#[cfg(feature = "ct-eq")]
248impl<T: ?Sized> crate::ConstantTimeEq for Dynamic<T>
249where
250 T: crate::ConstantTimeEq,
251{
252 fn ct_eq(&self, other: &Self) -> bool {
253 self.inner.ct_eq(&other.inner)
254 }
255}
256
257#[cfg(feature = "ct-eq")]
259impl Dynamic<String> {
260 #[inline]
265 pub fn ct_eq(&self, other: &Self) -> bool {
266 use crate::traits::ConstantTimeEq;
267 self.inner.as_bytes().ct_eq(other.inner.as_bytes())
268 }
269}
270
271#[cfg(feature = "ct-eq")]
272impl Dynamic<Vec<u8>> {
273 #[inline]
278 pub fn ct_eq(&self, other: &Self) -> bool {
279 use crate::traits::ConstantTimeEq;
280 self.inner.as_slice().ct_eq(other.inner.as_slice())
281 }
282}
283
284#[cfg(feature = "ct-eq-hash")]
285impl<T> crate::ConstantTimeEqExt for Dynamic<T>
286where
287 T: AsRef<[u8]> + crate::ConstantTimeEq + ?Sized,
288{
289 fn len(&self) -> usize {
290 (*self.inner).as_ref().len()
291 }
292
293 fn ct_eq_hash(&self, other: &Self) -> bool {
294 crate::traits::ct_eq_hash_bytes((*self.inner).as_ref(), (*other.inner).as_ref())
295 }
296 }
298
299impl<T: ?Sized> core::fmt::Debug for Dynamic<T> {
301 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
302 f.write_str("[REDACTED]")
303 }
304}
305
306#[cfg(feature = "cloneable")]
307impl<T: crate::CloneableType> Clone for Dynamic<T> {
308 fn clone(&self) -> Self {
309 Self::new(self.inner.clone())
310 }
311}
312
313#[cfg(feature = "serde-serialize")]
314impl<T> serde::Serialize for Dynamic<T>
315where
316 T: crate::SerializableType,
317{
318 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
319 where
320 S: serde::Serializer,
321 {
322 self.inner.serialize(serializer)
323 }
324}
325
326#[cfg(feature = "serde-deserialize")]
328impl<'de> serde::Deserialize<'de> for Dynamic<String> {
329 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
330 where
331 D: serde::Deserializer<'de>,
332 {
333 let s: String = serde::Deserialize::deserialize(deserializer)?;
334 Ok(Dynamic::new(s))
335 }
336}
337
338#[cfg(feature = "serde-deserialize")]
340impl<'de> serde::Deserialize<'de> for Dynamic<alloc::vec::Vec<u8>> {
341 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
342 where
343 D: serde::Deserializer<'de>,
344 {
345 let vec: alloc::vec::Vec<u8> = serde::Deserialize::deserialize(deserializer)?;
346 Ok(Dynamic::new(vec))
347 }
348}
349
350#[cfg(feature = "zeroize")]
352impl<T: ?Sized + zeroize::Zeroize> zeroize::Zeroize for Dynamic<T> {
353 fn zeroize(&mut self) {
354 self.inner.zeroize();
355 }
356}
357
358#[cfg(feature = "zeroize")]
360impl<T: ?Sized + zeroize::Zeroize> zeroize::ZeroizeOnDrop for Dynamic<T> {}