1use core::{mem, num, ops};
24
25pub trait BufferAllocator {
26 type Buffer<'source>: ops::DerefMut<Target=[mem::MaybeUninit<u8>]>
27 where Self: 'source;
28 type Error;
29
30 fn alloc<'source>(
31 &'source self,
32 size: num::NonZeroUsize,
33 ) -> Result<Self::Buffer<'source>, Self::Error>;
34}
35
36#[cfg(feature = "allocator-api")]
37pub mod allocator_api {
38 use core::{
39 alloc::{AllocError, Allocator, Layout, LayoutError},
40 error, fmt, mem, num, ops, ptr,
41 };
42
43 pub struct AllocBuf<'source, A>
44 where A: Allocator
45 {
46 allocation: ptr::NonNull<[u8]>,
47 layout: Layout,
48 allocator: &'source A,
49 }
50
51 impl<'source, A> ops::Deref for AllocBuf<'source, A>
52 where A: Allocator
53 {
54 type Target = [mem::MaybeUninit<u8>];
55 #[inline(always)]
56 fn deref(&self) -> &[mem::MaybeUninit<u8>] { unsafe { self.allocation.as_uninit_slice() } }
57 }
58
59 impl<'source, A> ops::DerefMut for AllocBuf<'source, A>
60 where A: Allocator
61 {
62 #[inline(always)]
63 fn deref_mut(&mut self) -> &mut [mem::MaybeUninit<u8>] {
64 unsafe { self.allocation.as_uninit_slice_mut() }
65 }
66 }
67
68 impl<'source, A> ops::Drop for AllocBuf<'source, A>
69 where A: Allocator
70 {
71 fn drop(&mut self) {
72 unsafe {
73 self
74 .allocator
75 .deallocate(self.allocation.cast(), self.layout);
76 }
77 }
78 }
79
80 #[derive(Debug)]
81 pub enum AllocatorError {
82 Alloc(AllocError),
83 Layout(LayoutError),
84 }
85
86 impl From<AllocError> for AllocatorError {
87 #[inline(always)]
88 fn from(e: AllocError) -> Self { Self::Alloc(e) }
89 }
90
91 impl From<LayoutError> for AllocatorError {
92 #[inline(always)]
93 fn from(e: LayoutError) -> Self { Self::Layout(e) }
94 }
95
96 impl fmt::Display for AllocatorError {
97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98 match self {
99 Self::Alloc(e) => fmt::Display::fmt(e, f),
100 Self::Layout(e) => fmt::Display::fmt(e, f),
101 }
102 }
103 }
104
105 impl error::Error for AllocatorError {
106 fn source(&self) -> Option<&(dyn error::Error+'static)> {
107 match self {
108 Self::Alloc(e) => Some(e),
109 Self::Layout(e) => Some(e),
110 }
111 }
112 }
113
114 impl<A> super::BufferAllocator for A
115 where A: Allocator
116 {
117 type Buffer<'source>
118 = AllocBuf<'source, A>
119 where Self: 'source;
120 type Error = AllocatorError;
121
122 fn alloc<'source>(
123 &'source self,
124 size: num::NonZeroUsize,
125 ) -> Result<Self::Buffer<'source>, Self::Error> {
126 let layout = Layout::array::<u8>(size.get())?;
127 let allocation = self.allocate(layout)?;
128 Ok(AllocBuf {
129 allocation,
130 layout,
131 allocator: self,
132 })
133 }
134 }
135}