use std::alloc::{alloc, dealloc, handle_alloc_error, Layout}; use std::mem::MaybeUninit; use std::ptr::NonNull; pub trait MaybeUninitByteSlice { unsafe fn cast(&self) -> &[Item]; } impl MaybeUninitByteSlice for &[MaybeUninit] { unsafe fn cast(&self) -> &[Item] { assert_eq!(self.len() % size_of::(), 0, "Invalid item size"); assert_eq!( self.as_ptr().addr() % align_of::(), 0, "Invalid item alignment" ); let new_len = self.len() / size_of::(); if new_len == 0 { return &[]; } unsafe { std::slice::from_raw_parts(self.as_ptr().cast::(), new_len) } } } #[derive(Debug)] pub struct AnonUnique { ptr: NonNull>, layout: Layout, } impl AnonUnique { pub fn new_uninit(layout: Layout) -> Self { if layout.size() == 0 { return Self { ptr: NonNull::dangling(), layout }; } let Some(ptr) = NonNull::new(unsafe { alloc(layout) }) else { handle_alloc_error(layout); }; Self { ptr: ptr.cast::>(), layout, } } pub fn layout(&self) -> &Layout { &self.layout } pub fn as_slice_mut(&mut self) -> &mut [MaybeUninit] { unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.layout.size()) } } pub fn as_slice(&self) -> &[MaybeUninit] { unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.layout.size()) } } pub fn as_ptr(&self) -> NonNull> { self.ptr } } impl Drop for AnonUnique { fn drop(&mut self) { if self.layout.size() == 0 { return; } unsafe { dealloc(self.ptr.as_ptr().cast(), self.layout); } } }