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}