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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
use core::ptr::NonNull;
use crate::{Align, Allocator, Error, Layout};
/// An allocation returned from (and tied to) an [`Allocator`].
///
/// Cannot outlive its allocator, nor can it be freed in another.
pub struct Alloc<'alloc, T: ?Sized> {
ptr: NonNull<T>,
layout: Layout,
allocator: &'alloc dyn Allocator,
}
impl<'alloc, T: ?Sized> Alloc<'alloc, T> {
/// # Safety
///
/// - `ptr` must have been allocated in `allocator`, and not have already
/// been deallocated.
/// - `layout` must be the layout used to allocate `ptr`.
/// - This must not be used to double-drop an allocation.
pub unsafe fn new(ptr: NonNull<T>, layout: Layout, allocator: &'alloc dyn Allocator) -> Self {
Self {
ptr,
layout,
allocator,
}
}
/// Returns the allocator internally associated with this allocation.
pub fn allocator(&self) -> &'alloc dyn Allocator {
self.allocator
}
/// Get a `NonNull` to the object.
///
/// Note that, when this is dropped, this pointer becomes invalid.
pub fn ptr(&self) -> NonNull<T> {
self.ptr
}
/// Get a raw pointer to the object.
///
/// Note that, when this is dropped, this pointer becomes invalid.
pub fn as_ptr(&self) -> *mut T {
self.ptr.as_ptr()
}
/// A shortcut for `self.ptr().as_ref()`.
///
/// # Safety
///
/// See [`NonNull::as_ref`].
pub unsafe fn as_ref(&self) -> &T {
self.ptr.as_ref()
}
/// A shortcut for `self.ptr().as_mut()`.
///
/// # Safety
///
/// See [`NonNull::as_mut`].
pub unsafe fn as_mut(&mut self) -> &mut T {
self.ptr.as_mut()
}
/// Write a value into this pointer.
///
/// Note that the old value is not dropped; see [`NonNull::write`].
pub fn write(&mut self, data: T)
where
T: Sized,
{
// SAFETY: ptr is aligned and valid
unsafe { self.ptr.write(data) };
}
/// Cast this pointer to another pointer.
///
/// Note that using this pointer is invalid if
/// `size_of::<Q>() > self.size()`. See [`NonNull::cast`].
pub fn cast<Q>(self) -> Alloc<'alloc, Q> {
let Self {
ptr,
layout,
allocator,
} = self;
Alloc {
ptr: ptr.cast(),
layout,
allocator,
}
}
/// Cast this into a slice of all bytes in the allocation.
///
/// Note that if the allocator returned a larger allocation than requested,
/// this won't observe those bytes: it will only expose `self.size()` bytes.
pub fn all_bytes(self) -> Alloc<'alloc, [u8]> {
let Self {
ptr,
layout,
allocator,
} = self;
let ptr = NonNull::slice_from_raw_parts(ptr.cast(), layout.size);
Alloc {
ptr,
layout,
allocator,
}
}
/// Returns the layout this was allocated with.
pub fn layout(&self) -> Layout {
self.layout
}
/// Returns the size this was allocated with.
///
/// Short for `self.layout().size`.
pub fn size(&self) -> usize {
self.layout.size
}
/// Returns the alignment this was allocated with.
///
/// Short for `self.layout().align`.
pub fn align(&self) -> Align {
self.layout.align
}
/// Deallocate this allocation in its allocator.
///
/// Shortcut for [`Allocator::dealloc`].
pub fn dealloc(self) {
self.allocator.dealloc_bytes(self.cast())
}
/// Reallocate this allocation in its allocator with a new layout.
///
/// Shortcut for [`Allocator::realloc`].
pub fn realloc(self, layout: Layout) -> Result<Alloc<'alloc, u8>, Error> {
self.allocator.realloc(self.cast(), layout)
}
/// Grow this allocation in its allocator with a new layout.
///
/// Shortcut for [`Allocator::grow`].
pub fn grow(self, layout: Layout) -> Result<Alloc<'alloc, u8>, Error> {
self.allocator.grow(self.cast(), layout)
}
/// Shrink this allocation in its allocator with a new layout.
///
/// Shortcut for [`Allocator::shrink`].
pub fn shrink(self, layout: Layout) -> Result<Alloc<'alloc, u8>, Error> {
self.allocator.shrink(self.cast(), layout)
}
}