use std::mem::MaybeUninit;
pub trait AssumeInit {
type Output;
unsafe fn assume_init(self) -> Self::Output;
}
impl<T> AssumeInit for Vec<MaybeUninit<T>> {
type Output = Vec<T>;
unsafe fn assume_init(mut self) -> Self::Output {
let (ptr, len, capacity) = (self.as_mut_ptr(), self.len(), self.capacity());
std::mem::forget(self);
unsafe { Vec::from_raw_parts(ptr as *mut T, len, capacity) }
}
}
impl<'a, T> AssumeInit for &'a [MaybeUninit<T>] {
type Output = &'a [T];
unsafe fn assume_init(self) -> Self::Output {
unsafe { std::mem::transmute(self) }
}
}
impl<'a, T> AssumeInit for &'a mut [MaybeUninit<T>] {
type Output = &'a mut [T];
unsafe fn assume_init(self) -> Self::Output {
unsafe { std::mem::transmute(self) }
}
}
#[cfg(test)]
mod tests {
use std::mem::MaybeUninit;
use super::AssumeInit;
#[test]
fn test_assume_init_vec() {
let mut vec = vec![MaybeUninit::uninit(); 3];
vec.reserve(4);
for x in &mut vec {
x.write(2.);
}
let vec = unsafe { vec.assume_init() };
assert_eq!(vec.len(), 3);
assert_eq!(vec.capacity(), 7);
assert_eq!(vec, &[2., 2., 2.]);
}
}