ps-alloc 0.1.0-9

a reasonably safe allocator
Documentation
use crate::{
    header::{initialize_block, layout_of, total_size},
    AllocationError,
};

/// A reasonably safe implementation of `alloc`.
///
/// Allocates a buffer of `size` bytes and returns a pointer to it. The buffer is
/// aligned to [`crate::HEADER_SIZE`] (16) bytes and is **not** initialized. `alloc(0)`
/// succeeds and returns a valid pointer to a zero-sized buffer.
///
/// Every returned pointer, including the zero-sized case, must eventually be released
/// with [`crate::free`] or [`crate::realloc`]; otherwise the allocation leaks.
///
/// # Errors
/// - `Err(ArithmeticError)` on integer overflow.
/// - `Err(LayoutError)` if the computed layout is invalid.
/// - `Err(OutOfMemory)` if the underlying allocator returns a null pointer.
pub fn alloc(size: usize) -> Result<*mut u8, AllocationError> {
    // the allocation size is header + size, rounded up
    let size = total_size(size)?;

    // allocations are aligned to [`crate::header::ALIGN`]
    let layout = layout_of(size)?;

    // SAFETY: `layout` has non-zero size, since `total_size` returns at least
    // `HEADER_SIZE` bytes.
    let ptr = unsafe { std::alloc::alloc(layout) };

    // note that [`std::alloc::alloc`] is allowed to abort instead
    if ptr.is_null() {
        return Err(AllocationError::OutOfMemory);
    }

    // the first [`crate::HEADER_SIZE`] bytes of the allocation are reserved for the
    // header; the user buffer starts directly after it
    // SAFETY: `ptr` is non-null, sufficiently aligned, and valid for writes of `size`
    // bytes, which include the header.
    Ok(unsafe { initialize_block(ptr, size) })
}