osom_lib_alloc/
std_allocator.rs1use core::{alloc::Layout, ptr::NonNull};
4
5use osom_lib_reprc::macros::reprc;
6
7use super::traits::{AllocationError, Allocator};
8
9#[derive(Debug, Default, Clone, Copy)]
11#[reprc]
12pub struct StdAllocator;
13
14#[derive(Debug, Clone, Copy)]
16#[reprc]
17pub enum StdAllocationError {
18 AllocationError = 0,
20
21 MisalignedResult = 1,
24}
25
26impl From<StdAllocationError> for AllocationError {
27 fn from(_: StdAllocationError) -> Self {
28 Self
29 }
30}
31
32unsafe impl Allocator for StdAllocator {
33 type SpecificAllocationError = StdAllocationError;
34
35 fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, Self::SpecificAllocationError> {
36 let raw_ptr = raw_aligned_malloc(layout);
37 if raw_ptr.is_null() {
38 return Err(StdAllocationError::AllocationError);
39 }
40
41 if raw_ptr.align_offset(layout.align()) != 0 {
42 raw_aligned_free(raw_ptr.cast(), layout);
43 return Err(StdAllocationError::MisalignedResult);
44 }
45
46 Ok(unsafe { NonNull::new_unchecked(raw_ptr.cast()) })
47 }
48
49 #[inline(always)]
50 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
51 raw_aligned_free(ptr.as_ptr().cast(), layout);
52 }
53
54 unsafe fn resize(
55 &self,
56 ptr: NonNull<u8>,
57 old_layout: Layout,
58 new_layout: Layout,
59 ) -> Result<NonNull<u8>, Self::SpecificAllocationError> {
60 let new_align = new_layout.align();
61 if old_layout.align() == new_align {
62 let raw_ptr = raw_aligned_realloc(ptr.as_ptr().cast(), old_layout, new_layout.size());
63 if raw_ptr.is_null() {
64 return Err(StdAllocationError::AllocationError);
65 }
66
67 if raw_ptr.align_offset(new_align) != 0 {
68 raw_aligned_free(raw_ptr.cast(), new_layout);
69 return Err(StdAllocationError::MisalignedResult);
70 }
71
72 Ok(unsafe { NonNull::new_unchecked(raw_ptr.cast()) })
73 } else {
74 unsafe {
75 let new_ptr = self.allocate(new_layout)?;
76 new_ptr.copy_from_nonoverlapping(ptr, new_layout.size());
77 self.deallocate(ptr, old_layout);
78 Ok(new_ptr)
79 }
80 }
81 }
82}
83
84osom_lib_cfg_ext::cfg_match!(
85 (miri) => {
86 extern crate alloc;
87
88 #[inline(always)]
89 fn raw_aligned_malloc(layout: Layout) -> *mut u8 {
90 unsafe { alloc::alloc::alloc(layout) }
91 }
92
93 #[inline(always)]
94 fn raw_aligned_realloc(ptr: *mut u8, old_layout: Layout, new_size: usize) -> *mut u8 {
95 unsafe { alloc::alloc::realloc(ptr, old_layout, new_size) }
96 }
97
98 #[inline(always)]
99 fn raw_aligned_free(ptr: *mut u8, layout: Layout) {
100 unsafe { alloc::alloc::dealloc(ptr, layout) }
101 }
102 },
103 (target_os="windows") => {
104 #[inline(always)]
105 fn raw_aligned_malloc(layout: Layout) -> *mut u8 {
106 unsafe { ::libc::aligned_malloc(layout.size(), layout.align()).cast() }
107 }
108
109 #[inline(always)]
110 fn raw_aligned_realloc(ptr: *mut u8, old_layout: Layout, new_size: usize) -> *mut u8 {
111 unsafe { ::libc::aligned_realloc(ptr.cast(), new_size, old_layout.align()).cast() }
112 }
113
114 #[inline(always)]
115 fn raw_aligned_free(ptr: *mut u8, _layout: Layout) {
116 unsafe { ::libc::aligned_free(ptr.cast()) }
117 }
118 },
119 _ => {
120 #[inline(always)]
121 fn raw_aligned_malloc(layout: Layout) -> *mut u8 {
122 unsafe { ::libc::malloc(layout.size()).cast() }
123 }
124
125 #[inline(always)]
126 fn raw_aligned_realloc(ptr: *mut u8, _old_layout: Layout, new_size: usize) -> *mut u8 {
127 unsafe { ::libc::realloc(ptr.cast(), new_size).cast() }
128 }
129
130 #[inline(always)]
131 fn raw_aligned_free(ptr: *mut u8, _layout: Layout) {
132 unsafe { ::libc::free(ptr.cast()) }
133 }
134 }
135);