#[cfg(test)]
mod tests;
use zeroize::Zeroize;
pub trait VecExtensions<T: Copy + Sized>: Zeroize {
fn with_value(value: &[T]) -> Vec<T>;
fn set_capacity_to(&mut self, capacity: usize);
fn set_capacity_to_secure(&mut self, capacity: usize);
fn set_contents_from_slice(&mut self, other: &[T]);
fn set_contents_from_slice_secure(&mut self, other: &[T]);
fn shrink_to_fit_secure(&mut self);
fn reserve_secure(&mut self, additional: usize);
fn extend_from_slice_secure(&mut self, other: &[T]);
}
macro_rules! vecextention_base_impl {
($type: ty) => {
impl VecExtensions<$type> for Vec<$type> {
fn with_value(value: &[$type]) -> Vec<$type> {
let mut obj = Vec::with_capacity(value.len());
obj.set_contents_from_slice(value);
obj
}
fn set_capacity_to(&mut self, capacity: usize) {
let curr_capacity = self.capacity();
if curr_capacity < capacity {
self.reserve(capacity - self.len());
}
}
fn set_capacity_to_secure(&mut self, capacity: usize) {
let curr_capacity = self.capacity();
if curr_capacity < capacity {
if self.is_empty() {
self.zeroize();
self.set_capacity_to(capacity);
} else if curr_capacity < capacity {
let mut tmp: Vec<$type> = Vec::with_capacity(self.len());
tmp.set_contents_from_slice(self.as_slice());
self.zeroize();
self.truncate(0);
self.set_capacity_to(capacity);
assert!(self.capacity() >= tmp.len());
unsafe {
std::ptr::copy_nonoverlapping(
tmp.as_ptr(),
self.as_mut_ptr(),
tmp.len(),
);
self.set_len(tmp.len());
}
tmp.zeroize();
}
}
}
fn set_contents_from_slice(&mut self, other: &[$type]) {
self.set_capacity_to(other.len());
unsafe {
self.set_len(other.len());
std::ptr::copy_nonoverlapping(other.as_ptr(), self.as_mut_ptr(), other.len());
}
}
fn set_contents_from_slice_secure(&mut self, other: &[$type]) {
self.zeroize();
self.reserve(other.len());
unsafe {
self.set_len(other.len());
std::ptr::copy_nonoverlapping(other.as_ptr(), self.as_mut_ptr(), other.len());
}
}
fn shrink_to_fit_secure(&mut self) {
let mut tmp: Vec<$type> = Vec::with_capacity(self.len());
tmp.set_contents_from_slice(self.as_slice());
self.zeroize();
self.shrink_to_fit();
self.set_contents_from_slice(tmp.as_slice());
tmp.zeroize();
}
fn reserve_secure(&mut self, additional: usize) {
self.set_capacity_to_secure(self.len() + additional);
}
fn extend_from_slice_secure(&mut self, other: &[$type]) {
self.reserve_secure(other.len());
assert!(self.capacity() >= self.len() + other.len());
unsafe {
std::ptr::copy_nonoverlapping(
other.as_ptr(),
self.as_mut_ptr().add(self.len()),
other.len(),
);
self.set_len(self.len() + other.len());
}
}
}
};
}
macro_rules! multi_vecextention_base_impl {
($type: ty) => {
vecextention_base_impl!($type);
};
($type: ty, $($type2: ty), +) => {
vecextention_base_impl! ($type);
multi_vecextention_base_impl!($($type2), +);
};
}
multi_vecextention_base_impl!(bool);
multi_vecextention_base_impl!(u8, u16, u32, u64, u128);
multi_vecextention_base_impl!(i8, i16, i32, i64, i128);
multi_vecextention_base_impl!(f32, f64);