osom_alloc/
lib.rs

1//! This crate defines allocator trait.
2//!
3//! The crate is `#![no_std]`.
4#![deny(warnings)]
5#![warn(clippy::all, clippy::pedantic)]
6#![no_std]
7
8use core::{alloc::Layout, fmt::Debug, ptr::NonNull};
9
10/// Represents a generic allocation error. Most likely represents out-of-memory state.
11#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Default)]
12#[repr(C)]
13pub struct AllocationError;
14
15/// Represents an Allocator.
16///
17/// # Safety
18///
19/// This trait is inherently unsafe, since it depends on well managed
20/// raw pointers. For example it is possible to call [`Allocator::deallocate`]
21/// twice on the same pointer, which is an Undefined Behaviour.
22pub unsafe trait Allocator: Debug + Default + Clone {
23    /// A specific Allocator error. Implementor can add additional
24    /// information to the error, not only generic "allocation failed".
25    type SpecificAllocationError: Into<AllocationError> + Debug;
26
27    /// Allocates new piece of memory. This is the only safe
28    /// function here. The returned `ptr` is guaranteed to satisfy
29    /// `layout` requirements (although the implementation is free
30    /// to overallocate and strengthen alignment).
31    ///
32    /// # Errors
33    ///
34    /// An error typically means out-of-memory error. But the implemtation
35    /// is allowed to provide additional info.
36    fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, Self::SpecificAllocationError>;
37
38    /// Deallocates memory.
39    ///
40    /// # Safety
41    ///
42    /// Passed `ptr` has to be created with previous call to [`Allocator::allocate`]
43    /// or [`Allocator::resize`]. Layouts have to match. Using the passed `ptr`
44    /// after the call to this function is an Undefined Behaviour.
45    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
46
47    /// Resizes given `ptr` to the new layout.
48    ///
49    /// # Errors
50    ///  
51    /// An error typically means out-of-memory error. But the implemtation
52    /// is allowed to provide additional info.
53    ///
54    /// # Safety
55    ///
56    /// `ptr` has to be a valid pointer created with previous call to
57    /// [`Allocator::allocate`] or [`Allocator::resize`]. `old_layout`
58    /// has to match the pointers layout. Using the passed ptr after
59    /// the call to this function is an Undefined Behaviour. Use the
60    /// return value instead.
61    unsafe fn resize(
62        &self,
63        ptr: NonNull<u8>,
64        old_layout: Layout,
65        new_layout: Layout,
66    ) -> Result<NonNull<u8>, Self::SpecificAllocationError> {
67        unsafe {
68            let new_ptr = self.allocate(new_layout)?;
69            new_ptr.copy_from_nonoverlapping(ptr, new_layout.size());
70            self.deallocate(ptr, old_layout);
71            Ok(new_ptr)
72        }
73    }
74}