1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! Define additional methods, used only by raw transfer:
//!
//! * [`Allocator::from_raw_parts`]
//! * [`Allocator::set_cursor_ptr`]
//! * [`Allocator::data_end_ptr`]
//! * [`Allocator::end_ptr`]
use std::ptr::NonNull;
use crate::{
Allocator,
bump::{Bump, CHUNK_ALIGN, CHUNK_FOOTER_SIZE},
};
impl Allocator {
/// Minimum size for memory chunk passed to [`Allocator::from_raw_parts`].
pub const RAW_MIN_SIZE: usize = CHUNK_FOOTER_SIZE;
/// Minimum alignment for memory chunk passed to [`Allocator::from_raw_parts`].
pub const RAW_MIN_ALIGN: usize = CHUNK_ALIGN;
/// Construct a static-sized [`Allocator`] from an existing memory allocation.
///
/// The [`Allocator`] which is returned takes ownership of the memory allocation,
/// and the allocation will be freed if the `Allocator` is dropped.
/// If caller wishes to prevent that happening, they must wrap the `Allocator` in `ManuallyDrop`.
///
/// The [`Allocator`] returned by this function cannot grow.
///
/// # SAFETY
///
/// * `ptr` must be aligned on [`RAW_MIN_ALIGN`].
/// * `size` must be a multiple of [`RAW_MIN_ALIGN`].
/// * `size` must be at least [`RAW_MIN_SIZE`].
/// * The memory region starting at `ptr` and encompassing `size` bytes must be within a single allocation.
/// * The memory region starting at `ptr` and encompassing `size` bytes must have been allocated from system
/// allocator with alignment of [`RAW_MIN_ALIGN`] (or caller must wrap the `Allocator` in `ManuallyDrop`
/// and ensure the backing memory is freed correctly themselves).
/// * `ptr` must have permission for writes.
///
/// [`RAW_MIN_ALIGN`]: Self::RAW_MIN_ALIGN
/// [`RAW_MIN_SIZE`]: Self::RAW_MIN_SIZE
pub unsafe fn from_raw_parts(ptr: NonNull<u8>, size: usize) -> Self {
// SAFETY: Safety requirements of `Bump::from_raw_parts` are the same as for this method
let bump = unsafe { Bump::from_raw_parts(ptr, size) };
Self::from_bump(bump)
}
/// Set cursor pointer for this [`Allocator`]'s current chunk.
///
/// This is dangerous, and this method should not ordinarily be used.
/// It is only here for manually resetting the allocator.
///
/// # SAFETY
///
/// * Allocator must have at least 1 allocated chunk.
/// It is UB to call this method on an `Allocator` which has not allocated
/// i.e. fresh from `Allocator::new`.
/// * `ptr` must point to within the `Allocator`'s current chunk.
/// * `ptr` must be equal to or after data pointer for this chunk.
/// * `ptr` must be equal to or before the chunk's `ChunkFooter`.
/// * No live references to data in the current chunk before `ptr` can exist.
pub unsafe fn set_cursor_ptr(&self, ptr: NonNull<u8>) {
// SAFETY: Caller guarantees `Allocator` has at least 1 allocated chunk, and `ptr` is valid.
// The `Bump` contained in `Allocator` has `MIN_ALIGN = 1`, so no alignment requirement for `ptr`.
unsafe { self.bump().set_cursor_ptr(ptr) };
}
/// Get pointer to end of the data region of this [`Allocator`]'s current chunk
/// i.e to the start of the `ChunkFooter`.
pub fn data_end_ptr(&self) -> NonNull<u8> {
self.bump().data_end_ptr()
}
/// Get pointer to end of this [`Allocator`]'s current chunk (after the `ChunkFooter`).
pub fn end_ptr(&self) -> NonNull<u8> {
self.bump().end_ptr()
}
}