use crate::{AcpiError, AcpiResult}; use core::{ alloc::{Allocator, Layout}, mem, ptr::NonNull, }; /// Thin wrapper around a regular slice, taking a reference to an allocator for automatic /// deallocation when the slice is dropped out of scope. #[derive(Debug)] pub struct ManagedSlice<'a, T, A> where A: Allocator, { slice: &'a mut [T], allocator: A, } impl<'a, T, A> ManagedSlice<'a, T, A> where A: Allocator, { /// Attempt to allocate a new `ManagedSlice` that holds `len` `T`s. pub fn new_in(len: usize, allocator: A) -> AcpiResult { let layout = Layout::array::(len).map_err(|_| AcpiError::AllocError)?; match allocator.allocate(layout) { Ok(mut ptr) => { let slice = unsafe { core::slice::from_raw_parts_mut(ptr.as_mut().as_mut_ptr().cast(), len) }; Ok(ManagedSlice { slice, allocator }) } Err(_) => Err(AcpiError::AllocError), } } } #[cfg(feature = "alloc")] impl<'a, T> ManagedSlice<'a, T, alloc::alloc::Global> { pub fn new(len: usize) -> AcpiResult { Self::new_in(len, alloc::alloc::Global) } } impl<'a, T, A> Drop for ManagedSlice<'a, T, A> where A: Allocator, { fn drop(&mut self) { unsafe { let slice_ptr = NonNull::new_unchecked(self.slice.as_ptr().cast_mut().cast::()); let slice_layout = Layout::from_size_align_unchecked(mem::size_of_val(self.slice), mem::align_of_val(self.slice)); self.allocator.deallocate(slice_ptr, slice_layout); } } } impl<'a, T, A> core::ops::Deref for ManagedSlice<'a, T, A> where A: Allocator, { type Target = [T]; fn deref(&self) -> &Self::Target { self.slice } } impl<'a, T, A> core::ops::DerefMut for ManagedSlice<'a, T, A> where A: Allocator, { fn deref_mut(&mut self) -> &mut Self::Target { self.slice } }