playdate_allocator/
global.rs1use core::alloc::{GlobalAlloc, Layout};
2use core::ffi::c_void;
3
4use crate::System;
5
6
7#[global_allocator]
9#[cfg(feature = "global")]
10pub static GLOBAL: System = System;
11
12
13unsafe impl GlobalAlloc for System {
14 #[inline]
15 unsafe fn alloc(&self, layout: Layout) -> *mut u8 { realloc(core::ptr::null_mut(), layout.size()) as *mut u8 }
16 #[inline]
17 unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { dealloc(ptr as *mut c_void); }
18 #[inline]
19 unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
20 let res = realloc(ptr as *mut c_void, new_size) as *mut u8;
21
22 if !res.is_null() && ptr != res {
24 unsafe {
27 core::ptr::copy_nonoverlapping(ptr, res, core::cmp::min(layout.size(), new_size));
28 self.dealloc(ptr, layout);
29 }
30 }
31
32 res
33 }
34
35 }
39
40
41#[track_caller]
42#[inline(always)]
43pub unsafe fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void { crate::get()(ptr, size) }
44
45
46#[track_caller]
47#[inline(always)]
48pub unsafe fn dealloc(ptr: *mut c_void) { realloc(ptr, 0); }
49
50
51#[track_caller]
53#[alloc_error_handler]
54#[cfg(feature = "global-error-handler")]
55fn alloc_error(layout: Layout) -> ! {
56 type Error = unsafe extern "C" fn(fmt: *const core::ffi::c_char, ...) -> !;
57 unsafe extern "Rust" {
58 #[link_name = "PDERR"]
59 pub static ERROR: core::mem::MaybeUninit<Error>;
60 }
61 if unsafe { ERROR.as_ptr() }.is_null() {
62 use core::intrinsics::is_val_statically_known;
63 if is_val_statically_known(layout.size() != 0) {
64 panic!("OoM: {}b", layout.size())
66 } else {
67 panic!("OoM")
69 }
70 } else {
71 use numtoa_like::*;
72 let mut s = [79, 111, 77, 58, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 0];
74 let mut index = s.len() - 3;
75 render(layout.size(), &mut index, &mut s);
76 s[5..].rotate_left(index.wrapping_sub(3));
77
78 unsafe {
80 let f = ERROR.assume_init();
81 f(s.as_ptr().cast())
82 }
83 }
84}
85
86
87#[cfg(feature = "global-error-handler")]
88mod numtoa_like {
89 const LOOKUP: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
92 const DEC_LOOKUP: &[u8; 200] = b"0001020304050607080910111213141516171819\
94 2021222324252627282930313233343536373839\
95 4041424344454647484950515253545556575859\
96 6061626364656667686970717273747576777879\
97 8081828384858687888990919293949596979899";
98
99 pub fn render(value: usize, index: &mut usize, buf: &mut [u8]) {
102 let mut v = value;
103 while v > 9999 {
105 let rem = (v % 10000) as u16;
106 let (frst, scnd) = ((rem / 100) * 2, (rem % 100) * 2);
107 buf[*index - 3..*index - 1].copy_from_slice(&DEC_LOOKUP[frst as usize..frst as usize + 2]);
108 buf[*index - 1..*index + 1].copy_from_slice(&DEC_LOOKUP[scnd as usize..scnd as usize + 2]);
109 *index = index.wrapping_sub(4);
110 v /= 10000;
111 }
112 if v > 999 {
113 let (frst, scnd) = ((v / 100) * 2, (v % 100) * 2);
114 buf[*index - 3..*index - 1].copy_from_slice(&DEC_LOOKUP[frst as usize..frst as usize + 2]);
115 buf[*index - 1..*index + 1].copy_from_slice(&DEC_LOOKUP[scnd as usize..scnd as usize + 2]);
116 *index = index.wrapping_sub(4);
117 } else if v > 99 {
118 let section = (v as u16 / 10) * 2;
119 buf[*index - 2..*index].copy_from_slice(&DEC_LOOKUP[section as usize..section as usize + 2]);
120 buf[*index] = LOOKUP[(v % 10) as usize];
121 *index = index.wrapping_sub(3);
122 } else if v > 9 {
123 v *= 2;
124 buf[*index - 1..*index + 1].copy_from_slice(&DEC_LOOKUP[v as usize..v as usize + 2]);
125 *index = index.wrapping_sub(2);
126 } else {
127 buf[*index] = LOOKUP[v as usize];
128 *index = index.wrapping_sub(1);
129 }
130 }
131}