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}