1 use crate::{AcpiError, AcpiResult};
2 use core::{
3     alloc::{Allocator, Layout},
4     mem,
5     ptr::NonNull,
6 };
7 
8 /// Thin wrapper around a regular slice, taking a reference to an allocator for automatic
9 /// deallocation when the slice is dropped out of scope.
10 #[derive(Debug)]
11 pub struct ManagedSlice<'a, T, A>
12 where
13     A: Allocator,
14 {
15     slice: &'a mut [T],
16     allocator: A,
17 }
18 
19 impl<'a, T, A> ManagedSlice<'a, T, A>
20 where
21     A: Allocator,
22 {
23     /// Attempt to allocate a new `ManagedSlice` that holds `len` `T`s.
new_in(len: usize, allocator: A) -> AcpiResult<Self>24     pub fn new_in(len: usize, allocator: A) -> AcpiResult<Self> {
25         let layout = Layout::array::<T>(len).map_err(|_| AcpiError::AllocError)?;
26         match allocator.allocate(layout) {
27             Ok(mut ptr) => {
28                 let slice = unsafe { core::slice::from_raw_parts_mut(ptr.as_mut().as_mut_ptr().cast(), len) };
29                 Ok(ManagedSlice { slice, allocator })
30             }
31             Err(_) => Err(AcpiError::AllocError),
32         }
33     }
34 }
35 
36 #[cfg(feature = "alloc")]
37 impl<'a, T> ManagedSlice<'a, T, alloc::alloc::Global> {
new(len: usize) -> AcpiResult<Self>38     pub fn new(len: usize) -> AcpiResult<Self> {
39         Self::new_in(len, alloc::alloc::Global)
40     }
41 }
42 
43 impl<'a, T, A> Drop for ManagedSlice<'a, T, A>
44 where
45     A: Allocator,
46 {
drop(&mut self)47     fn drop(&mut self) {
48         unsafe {
49             let slice_ptr = NonNull::new_unchecked(self.slice.as_ptr().cast_mut().cast::<u8>());
50             let slice_layout =
51                 Layout::from_size_align_unchecked(mem::size_of_val(self.slice), mem::align_of_val(self.slice));
52             self.allocator.deallocate(slice_ptr, slice_layout);
53         }
54     }
55 }
56 
57 impl<'a, T, A> core::ops::Deref for ManagedSlice<'a, T, A>
58 where
59     A: Allocator,
60 {
61     type Target = [T];
62 
deref(&self) -> &Self::Target63     fn deref(&self) -> &Self::Target {
64         self.slice
65     }
66 }
67 
68 impl<'a, T, A> core::ops::DerefMut for ManagedSlice<'a, T, A>
69 where
70     A: Allocator,
71 {
deref_mut(&mut self) -> &mut Self::Target72     fn deref_mut(&mut self) -> &mut Self::Target {
73         self.slice
74     }
75 }
76