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<Self> { | |
let layout = Layout::array::<T>(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> { | |
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::<u8>()); | |
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 | |
} | |
} |