pebble_skip/standard_c/
memory.rs1use core::{
2 cmp::Ordering,
3 convert::TryInto,
4 intrinsics::drop_in_place,
5 mem::{needs_drop, size_of, size_of_val_raw, MaybeUninit},
6 ptr::NonNull,
7 slice,
8};
9use pebble_sys::{
10 prelude::*,
11 standard_c::memory::{self as sys_memory, void},
12};
13
14pub fn malloc<'a, T>() -> Result<&'a mut MaybeUninit<T>, ()> {
24 match size_of::<T>() {
25 0 => Ok(unsafe { &mut *(NonNull::dangling().as_ptr()) }),
26 size => unsafe { sys_memory::malloc(size).cast_unchecked_mut() }.ok_or(()),
27 }
28}
29
30pub fn malloc_buffer_uninit<'a>(len: usize) -> Result<&'a mut [MaybeUninit<u8>], ()> {
34 match len {
35 0 => Ok(unsafe {
36 slice::from_raw_parts_mut(NonNull::<u8>::dangling().as_ptr() as *mut _, 0)
37 }),
38 size => Ok(unsafe {
39 slice::from_raw_parts_mut(
40 sys_memory::malloc(size).cast_unchecked_mut().ok_or(())?,
41 size,
42 )
43 }),
44 }
45}
46
47pub fn calloc<'a, T>(count: usize) -> Result<&'a mut [MaybeUninit<T>], ()> {
57 match size_of::<T>() {
58 0 => Ok(unsafe { slice::from_raw_parts_mut(NonNull::dangling().as_ptr(), count) }),
59 size => match unsafe {
60 sys_memory::calloc(count, size)
61 .map(|mem| slice::from_raw_parts_mut(mem.cast_unchecked_mut(), count))
62 } {
63 Some(uninit) => Ok(uninit),
64 None => Err(()),
65 },
66 }
67}
68
69pub enum ReallocOk<'a, T> {
71 ShrunkenOrEqual(&'a mut [T]),
72 Grown(&'a mut [MaybeUninit<T>]),
73}
74
75pub enum ReallocError<'a, T> {
77 CouldNotGrowOrMove(&'a mut [T]),
78 CouldNotShrink(&'a mut [MaybeUninit<T>]),
79}
80
81#[allow(clippy::type_complexity)]
100pub unsafe fn resize_realloc<'a, T>(
101 buffer: &'static mut [T],
102 new_len: usize,
103) -> Result<ReallocOk<'a, T>, ReallocError<'a, T>> {
104 let size = size_of::<T>();
105 let old_len = buffer.len();
106 let old_ptr = &mut buffer[0] as *mut T;
107 if needs_drop::<T>() && new_len < old_len {
108 for discarded in slice::from_raw_parts_mut(
109 old_ptr.offset(new_len.try_into().expect("`new_len` overflow")),
110 old_len - new_len,
111 ) {
112 drop_in_place(discarded)
113 }
114 }
115 match sys_memory::realloc(
116 old_ptr as *mut _ as *mut void,
117 size.checked_mul(new_len).expect("size overflow"),
118 ) {
119 Some(new_ptr) => Ok(if old_len >= new_len {
120 ReallocOk::ShrunkenOrEqual(slice::from_raw_parts_mut(
121 new_ptr as *mut _ as *mut T,
122 new_len,
123 ))
124 } else {
125 ReallocOk::Grown(slice::from_raw_parts_mut(
126 new_ptr as *mut _ as *mut MaybeUninit<T>,
127 new_len,
128 ))
129 }),
130 None => Err(if new_len >= old_len {
131 ReallocError::CouldNotGrowOrMove(slice::from_raw_parts_mut(old_ptr, old_len))
132 } else {
133 ReallocError::CouldNotShrink(slice::from_raw_parts_mut(
134 old_ptr as *mut _ as *mut MaybeUninit<T>,
135 old_len,
136 ))
137 }),
138 }
139}
140
141pub unsafe fn drop_free<T: ?Sized>(slot: &'static mut T) {
147 let ptr = slot as *mut T;
148 drop_in_place(ptr);
149 match size_of_val_raw(ptr) {
150 0 => (),
151 _ => sys_memory::free(&mut *(ptr as *mut _)),
152 }
153}
154
155#[must_use]
161#[track_caller]
162pub fn memcmp(slice1: &[u8], slice2: &[u8]) -> Ordering {
163 if slice1.len() != slice2.len() {
164 panic!("Tried to memcmp slices of different sizes")
165 }
166
167 match unsafe { sys_memory::memcmp(slice1.upcast(), slice2.upcast(), slice1.len()) } {
168 i32::MIN..=-1 => Ordering::Greater,
169 0 => Ordering::Equal,
170 1..=i32::MAX => Ordering::Less,
171 }
172}
173
174pub unsafe fn memcpy<T>(dest: &mut [T], src: &[T]) {
178 if src.len() != dest.len() {
179 panic!("Tried to memcpy between slices of different sizes")
180 }
181
182 sys_memory::memcpy(
183 (&mut *dest).upcast_mut(),
184 src.upcast(),
185 src.len() * size_of::<T>(),
186 );
187}
188
189pub unsafe fn memcpy_uninit<T>(dest: &mut [MaybeUninit<T>], src: &[T]) {
193 if src.len() != dest.len() {
194 panic!("Tried to memcpy between slices of different sizes")
195 }
196
197 sys_memory::memcpy(
198 (&mut *dest).upcast_mut(),
199 src.upcast(),
200 src.len() * size_of::<T>(),
201 );
202}
203
204pub fn memset(dest: &mut [u8], c: u8) {
206 let len = dest.len();
207 unsafe { sys_memory::memset((&mut *dest).upcast_mut(), c.into(), len) };
208}