iceoryx2_bb_elementary_traits/
allocator.rs

1// Copyright (c) 2023 Contributors to the Eclipse Foundation
2//
3// See the NOTICE file(s) distributed with this work for additional
4// information regarding copyright ownership.
5//
6// This program and the accompanying materials are made available under the
7// terms of the Apache Software License 2.0 which is available at
8// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
9// which is available at https://opensource.org/licenses/MIT.
10//
11// SPDX-License-Identifier: Apache-2.0 OR MIT
12
13//! Contains the traits [`BaseAllocator`] which contains the most basic functionality an allocator
14//! requires and [`Allocator`] with more advanced allocation features.
15
16pub use core::{alloc::Layout, ptr::NonNull};
17
18/// Failures caused by [`BaseAllocator::allocate()`] or [`BaseAllocator::allocate_zeroed()`].
19#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
20pub enum AllocationError {
21    SizeIsZero,
22    SizeTooLarge,
23    AlignmentFailure,
24    OutOfMemory,
25    InternalError,
26}
27
28impl core::fmt::Display for AllocationError {
29    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
30        write!(f, "AllocationError::{self:?}")
31    }
32}
33
34impl core::error::Error for AllocationError {}
35
36/// Failures caused by [`Allocator::grow()`] or [`Allocator::grow_zeroed()`].
37#[derive(Debug, PartialEq, Eq, Copy, Clone)]
38pub enum AllocationGrowError {
39    GrowWouldShrink,
40    SizeIsZero,
41    OutOfMemory,
42    AlignmentFailure,
43    InternalError,
44}
45
46impl core::fmt::Display for AllocationGrowError {
47    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
48        write!(f, "AllocationGrowError::{self:?}")
49    }
50}
51
52impl core::error::Error for AllocationGrowError {}
53
54/// Failures caused by [`Allocator::shrink()`].
55#[derive(Debug, PartialEq, Eq, Copy, Clone)]
56pub enum AllocationShrinkError {
57    ShrinkWouldGrow,
58    SizeIsZero,
59    AlignmentFailure,
60    InternalError,
61}
62
63impl core::fmt::Display for AllocationShrinkError {
64    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
65        write!(f, "AllocationShrinkError::{self:?}")
66    }
67}
68
69impl core::error::Error for AllocationShrinkError {}
70
71/// The most minimalistic requirement for an allocator
72pub trait BaseAllocator {
73    /// Allocates a memory chunk with the properties provided in layout and either
74    /// returns a slice or an allocation error on failure.
75    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocationError>;
76
77    /// Allocates a memory chunk with the properties provided in layout and zeroes the memory
78    /// On success it returns a slice or an allocation error on failure.
79    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocationError> {
80        let memory = self.allocate(layout)?;
81        unsafe {
82            core::ptr::write_bytes(
83                memory.as_ref().as_ptr() as *mut u8,
84                0,
85                memory.as_ref().len(),
86            )
87        };
88        Ok(memory)
89    }
90
91    /// Releases an previously allocated chunk of memory.
92    ///
93    /// # Safety
94    ///
95    ///  * `ptr` must be allocated previously with [`BaseAllocator::allocate()`] or
96    ///    [`BaseAllocator::allocate_zeroed()`]
97    ///  * `layout` must have the same value as in the allocation or, when the memory was
98    ///    resized, the same value as it was resized to
99    ///
100    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
101}
102
103/// Allocator with grow and shrink features.
104pub trait Allocator: BaseAllocator {
105    /// Increases the size of an previously allocated chunk of memory or allocates a new chunk
106    /// with the provided properties.
107    /// It returns a failure when the size decreases.
108    ///
109    /// # Safety
110    ///
111    ///  * `ptr` must be allocated previously with [`BaseAllocator::allocate()`] or
112    ///    [`BaseAllocator::allocate_zeroed()`]
113    ///  * `old_layout` must have the same value as in the allocation or, when the memory was
114    ///    resized, the same value as it was resized to
115    ///
116    unsafe fn grow(
117        &self,
118        ptr: NonNull<u8>,
119        old_layout: Layout,
120        new_layout: Layout,
121    ) -> Result<NonNull<[u8]>, AllocationGrowError>;
122
123    /// Increases the size of an previously allocated chunk of memory or allocates a new chunk
124    /// with the provided properties. If the chunk can be resized only the difference in size
125    /// will be zeroed.
126    /// It returns a failure when the size decreases.
127    ///
128    /// # Safety
129    ///
130    ///  * `ptr` must be allocated previously with [`BaseAllocator::allocate()`] or
131    ///    [`BaseAllocator::allocate_zeroed()`]
132    ///  * `old_layout` must have the same value as in the allocation or, when the memory was
133    ///    resized, the same value as it was resized to
134    ///
135    unsafe fn grow_zeroed(
136        &self,
137        ptr: NonNull<u8>,
138        old_layout: Layout,
139        new_layout: Layout,
140    ) -> Result<NonNull<[u8]>, AllocationGrowError> {
141        let memory = self.grow(ptr, old_layout, new_layout)?;
142        core::ptr::write_bytes(
143            memory.as_ref().as_ptr().add(old_layout.size()) as *mut u8,
144            0,
145            memory.as_ref().len() - old_layout.size(),
146        );
147        Ok(memory)
148    }
149
150    /// Decreases the size of an previously allocated chunk of memory. If the size increases it
151    /// fails.
152    ///
153    /// # Safety
154    ///
155    ///  * `ptr` must be allocated previously with [`BaseAllocator::allocate()`] or
156    ///    [`BaseAllocator::allocate_zeroed()`]
157    ///  * `old_layout` must have the same value as in the allocation or, when the memory was
158    ///    resized, the same value as it was resized to
159    ///
160    unsafe fn shrink(
161        &self,
162        ptr: NonNull<u8>,
163        old_layout: Layout,
164        new_layout: Layout,
165    ) -> Result<NonNull<[u8]>, AllocationShrinkError>;
166}