stak_libc/
heap.rs

1use core::{mem::align_of, ptr::write, slice};
2
3/// A memory block on a heap.
4pub struct Heap<T> {
5    ptr: *mut T,
6    len: usize,
7}
8
9impl<T> Heap<T> {
10    /// Creates a heap.
11    pub fn new(len: usize, default: impl Fn() -> T) -> Self {
12        let mut this = Self {
13            // SAFETY: We allow memory access only within `len`.
14            ptr: unsafe { libc::malloc(len * align_of::<T>()) } as _,
15            len,
16        };
17
18        for x in this.as_slice_mut() {
19            // SAFETY: `x` is not initialized yet.
20            unsafe { write(x, default()) };
21        }
22
23        this
24    }
25
26    /// Returns a slice.
27    pub const fn as_slice(&mut self) -> &[T] {
28        // SAFETY: `self.ptr` has the length of `self.len`.
29        unsafe { slice::from_raw_parts(self.ptr as _, self.len) }
30    }
31
32    /// Returns a mutable slice.
33    pub const fn as_slice_mut(&mut self) -> &mut [T] {
34        // SAFETY: `self.ptr` has the length of `self.len`.
35        unsafe { slice::from_raw_parts_mut(self.ptr as _, self.len) }
36    }
37}
38
39impl<T> Drop for Heap<T> {
40    fn drop(&mut self) {
41        // SAFETY: The previous `malloc` call is guaranteed to have succeeded.
42        unsafe { libc::free(self.ptr as _) }
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn new() {
52        Heap::<usize>::new(42, || 42);
53    }
54
55    #[test]
56    fn new_zero_sized() {
57        Heap::<usize>::new(0, || 42);
58    }
59}