stak_libc/
heap.rs

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