osom_lib_alloc/
std_allocator.rs1extern crate alloc;
3
4use core::{alloc::Layout, convert::Infallible, ptr::NonNull};
5
6use osom_lib_reprc::macros::reprc;
7use osom_lib_try_clone::TryClone;
8
9use super::traits::{Allocator, WithMessage};
10
11#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
13#[reprc]
14pub struct StdAllocator;
15
16impl TryClone for StdAllocator {
17 type Error = Infallible;
18
19 fn try_clone(&self) -> Result<Self, Self::Error> {
20 Ok(*self)
21 }
22}
23
24#[derive(Debug, PartialEq, Eq, Clone, Copy)]
26#[reprc]
27pub enum StdAllocationError {
28 AllocationError = 0,
30
31 MisalignedResult = 1,
34}
35
36impl WithMessage for StdAllocationError {
37 fn message(&self) -> &str {
38 match self {
39 StdAllocationError::AllocationError => "Allocation failed",
40 StdAllocationError::MisalignedResult => "Misaligned result",
41 }
42 }
43}
44
45impl TryClone for StdAllocationError {
46 type Error = Infallible;
47
48 fn try_clone(&self) -> Result<Self, Self::Error> {
49 Ok(*self)
50 }
51}
52
53unsafe impl Allocator for StdAllocator {
54 type SpecificAllocationError = StdAllocationError;
55
56 fn allocate(&mut self, layout: Layout) -> Result<NonNull<u8>, Self::SpecificAllocationError> {
57 let raw_ptr = raw_aligned_malloc(layout);
58 if raw_ptr.is_null() {
59 return Err(StdAllocationError::AllocationError);
60 }
61
62 if raw_ptr.align_offset(layout.align()) != 0 {
63 raw_aligned_free(raw_ptr.cast(), layout);
64 return Err(StdAllocationError::MisalignedResult);
65 }
66
67 Ok(unsafe { NonNull::new_unchecked(raw_ptr.cast()) })
68 }
69
70 #[inline(always)]
71 unsafe fn deallocate(&mut self, ptr: NonNull<u8>, layout: Layout) {
72 raw_aligned_free(ptr.as_ptr().cast(), layout);
73 }
74
75 unsafe fn resize(
76 &mut self,
77 ptr: NonNull<u8>,
78 old_layout: Layout,
79 new_layout: Layout,
80 ) -> Result<NonNull<u8>, Self::SpecificAllocationError> {
81 let new_align = new_layout.align();
82 if old_layout.align() == new_align {
83 let raw_ptr = raw_aligned_realloc(ptr.as_ptr().cast(), old_layout, new_layout.size());
84 if raw_ptr.is_null() {
85 return Err(StdAllocationError::AllocationError);
86 }
87
88 if raw_ptr.align_offset(new_align) != 0 {
89 raw_aligned_free(raw_ptr.cast(), new_layout);
90 return Err(StdAllocationError::MisalignedResult);
91 }
92
93 Ok(unsafe { NonNull::new_unchecked(raw_ptr.cast()) })
94 } else {
95 unsafe {
96 let new_ptr = self.allocate(new_layout)?;
97 let size = core::cmp::min(new_layout.size(), old_layout.size());
98 new_ptr.copy_from_nonoverlapping(ptr, size);
99 self.deallocate(ptr, old_layout);
100 Ok(new_ptr)
101 }
102 }
103 }
104}
105
106#[inline(always)]
107fn raw_aligned_malloc(layout: Layout) -> *mut u8 {
108 unsafe { alloc::alloc::alloc(layout) }
109}
110
111#[inline(always)]
112fn raw_aligned_realloc(ptr: *mut u8, old_layout: Layout, new_size: usize) -> *mut u8 {
113 unsafe { alloc::alloc::realloc(ptr, old_layout, new_size) }
114}
115
116#[inline(always)]
117fn raw_aligned_free(ptr: *mut u8, layout: Layout) {
118 unsafe { alloc::alloc::dealloc(ptr, layout) }
119}