osom_lib_alloc/
traits.rs

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