secure_gate/cloneable/
vec.rs

1use crate::Dynamic;
2use zeroize::Zeroize;
3
4/// Inner wrapper for a vector of bytes that can be safely cloned as a secret.
5///
6/// This struct wraps a `Vec<u8>` and implements the necessary traits for secure
7/// secret handling: `Clone` for duplication and `Zeroize` for secure memory wiping.
8/// The `zeroize(drop)` attribute ensures the vector contents are zeroized when
9/// this struct is dropped.
10#[derive(Clone, Zeroize)]
11#[zeroize(drop)]
12pub struct CloneableVecInner(Vec<u8>);
13
14impl crate::CloneSafe for CloneableVecInner {}
15
16/// A dynamically-sized vector of bytes wrapped as a cloneable secret.
17///
18/// This type provides a secure wrapper around a `Vec<u8>` that can be safely cloned
19/// while ensuring the underlying data is properly zeroized when no longer needed.
20/// Use this for variable-length secret data like encrypted payloads or keys.
21///
22/// # Examples
23///
24/// ```
25/// # #[cfg(feature = "zeroize")]
26/// # {
27/// use secure_gate::CloneableVec;
28///
29/// // Create from a vector
30/// let data: CloneableVec = vec![1, 2, 3, 4].into();
31///
32/// // Create from a slice
33/// let data2: CloneableVec = b"hello world".as_slice().into();
34///
35/// // Access the inner vector
36/// let inner = data.expose_inner();
37/// assert_eq!(inner.len(), 4);
38/// # }
39/// ```
40pub type CloneableVec = Dynamic<CloneableVecInner>;
41
42impl CloneableVec {
43    /// Returns a reference to the inner vector without cloning.
44    ///
45    /// This method provides direct access to the wrapped `Vec<u8>`.
46    /// The reference is valid for the lifetime of the `CloneableVec`.
47    #[inline(always)]
48    pub const fn expose_inner(&self) -> &Vec<u8> {
49        &self.expose_secret().0
50    }
51
52    /// Returns a mutable reference to the inner vector.
53    ///
54    /// This method provides direct mutable access to the wrapped `Vec<u8>`.
55    /// Use this when you need to modify the vector contents in-place.
56    #[inline(always)]
57    pub fn expose_inner_mut(&mut self) -> &mut Vec<u8> {
58        &mut self.expose_secret_mut().0
59    }
60
61    /// Construct a cloneable vec secret by building it in a closure.
62    ///
63    /// Same stack-minimization benefits as `CloneableString::init_with`.
64    ///
65    /// # Example
66    ///
67    /// ```
68    /// # #[cfg(feature = "zeroize")]
69    /// # {
70    /// use secure_gate::CloneableVec;
71    ///
72    /// let seed = CloneableVec::init_with(|| {
73    ///     let mut v = vec![0u8; 32];
74    ///     // Fill from some source...
75    ///     v
76    /// });
77    /// # }
78    /// ```
79    #[must_use]
80    pub fn init_with<F>(constructor: F) -> Self
81    where
82        F: FnOnce() -> Vec<u8>,
83    {
84        let mut tmp = constructor();
85        let secret = Self::from(tmp.clone());
86        tmp.zeroize();
87        secret
88    }
89
90    /// Fallible version of `init_with`.
91    ///
92    /// Same stack-minimization benefits as `init_with`, but allows for construction
93    /// that may fail with an error. Useful when reading secrets from fallible sources
94    /// like files or network connections.
95    pub fn try_init_with<F, E>(constructor: F) -> Result<Self, E>
96    where
97        F: FnOnce() -> Result<Vec<u8>, E>,
98    {
99        let mut tmp = constructor()?;
100        let secret = Self::from(tmp.clone());
101        tmp.zeroize();
102        Ok(secret)
103    }
104}
105
106/// Wrap a `Vec<u8>` in a `CloneableVec`.
107impl From<Vec<u8>> for CloneableVec {
108    fn from(value: Vec<u8>) -> Self {
109        Dynamic::new(CloneableVecInner(value))
110    }
111}
112
113/// Wrap a byte slice in a `CloneableVec`.
114impl From<&[u8]> for CloneableVec {
115    fn from(value: &[u8]) -> Self {
116        Self::from(value.to_vec())
117    }
118}