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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
//! An initialized, writeable location in memory.
use core::{mem::size_of, ptr::NonNull};
use munge::{Borrow, Destructure, Restructure};
use crate::traits::{LayoutRaw, NoUndef};
/// A place to write a `T` paired with its position in the output buffer.
pub struct Place<T: ?Sized> {
pos: usize,
ptr: NonNull<T>,
}
impl<T: ?Sized> Clone for Place<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: ?Sized> Copy for Place<T> {}
impl<T: ?Sized> Place<T> {
/// Creates a new `Place` from an output pointer.
///
/// # Safety
///
/// `ptr` must be properly aligned, dereferenceable, and all of its bytes
/// must be initialized.
pub unsafe fn new_unchecked(pos: usize, ptr: *mut T) -> Self {
unsafe {
Self {
pos,
ptr: NonNull::new_unchecked(ptr),
}
}
}
/// Creates a new `Place` from a parent pointer and the field the place
/// points to.
///
/// # Safety
///
/// - `ptr` must point to a field of `parent`
/// - `ptr` must be properly aligned, dereferenceable, and all of its bytes
/// must be initialized
pub unsafe fn from_field_unchecked<U: ?Sized>(
parent: Place<U>,
ptr: *mut T,
) -> Self {
// SAFETY: We won't write anything to the parent pointer, so we
// definitely won't write any uninitialized bytes.
let parent_ptr = unsafe { parent.ptr() };
let offset = ptr as *mut () as usize - parent_ptr as *mut () as usize;
// SAFETY: The caller has guaranteed that `ptr` is properly aligned,
// dereferenceable, and all of its bytes are initialized.
unsafe { Self::new_unchecked(parent.pos() + offset, ptr) }
}
/// Returns the position of the place.
pub fn pos(&self) -> usize {
self.pos
}
/// Returns the pointer associated with this place.
///
/// # Safety
///
/// Uninitialized bytes must not be written to the returned pointer.
pub unsafe fn ptr(&self) -> *mut T {
self.ptr.as_ptr()
}
/// Writes the provided value to this place.
///
/// # Safety
///
/// `value` must not have any uninitialized bytes (e.g. padding).
pub unsafe fn write_unchecked(&self, value: T)
where
T: Sized,
{
unsafe {
self.ptr().write(value);
}
}
/// Writes the provided value to this place.
pub fn write(&self, value: T)
where
T: NoUndef + Sized,
{
unsafe {
self.write_unchecked(value);
}
}
/// Returns this place casted to the given type.
///
/// # Safety
///
/// This place must point to a valid `U`.
pub unsafe fn cast_unchecked<U>(&self) -> Place<U>
where
T: Sized,
{
Place {
pos: self.pos,
ptr: self.ptr.cast(),
}
}
/// Returns a slice of the bytes this place points to.
pub fn as_slice(&self) -> &[u8]
where
T: LayoutRaw,
{
let ptr = self.ptr.as_ptr();
let len = T::layout_raw(ptr_meta::metadata(ptr)).unwrap().size();
// SAFETY: The pointers of places are always properly aligned and
// dereferenceable. All of the bytes this place points to are guaranteed
// to be initialized at all times.
unsafe { core::slice::from_raw_parts(ptr.cast::<u8>(), len) }
}
}
impl<T> Place<[T]> {
/// Gets a `Place` to the `i`-th element of the slice.
///
/// # Safety
///
/// `i` must be in-bounds for the slice pointed to by this place.
pub unsafe fn index(&self, i: usize) -> Place<T> {
// SAFETY: The caller has guaranteed that `i` is in-bounds for the slice
// pointed to by this place.
let ptr = unsafe { self.ptr().cast::<T>().add(i) };
// SAFETY: `ptr` is an element of `self`, and so is also properly
// aligned, dereferenceable, and all of its bytes are initialized.
unsafe { Place::new_unchecked(self.pos() + i * size_of::<T>(), ptr) }
}
}
impl<T, const N: usize> Place<[T; N]> {
/// Gets a `Place` to the `i`-th element of the array.
///
/// # Safety
///
/// `i` must be in-bounds for the array pointed to by this place.
pub unsafe fn index(&self, i: usize) -> Place<T> {
// SAFETY: The caller has guaranteed that `i` is in-bounds for the array
// pointed to by this place.
let ptr = unsafe { self.ptr().cast::<T>().add(i) };
// SAFETY: `ptr` is an element of `self`, and so is also properly
// aligned, dereferenceable, and all of its bytes are initialized.
unsafe { Place::new_unchecked(self.pos() + i * size_of::<T>(), ptr) }
}
}
unsafe impl<T: ?Sized> Destructure for Place<T> {
type Underlying = T;
type Destructuring = Borrow;
fn underlying(&mut self) -> *mut Self::Underlying {
self.ptr.as_ptr()
}
}
unsafe impl<T: ?Sized, U: ?Sized> Restructure<U> for Place<T> {
type Restructured = Place<U>;
unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured {
// SAFETY: `ptr` is a pointer to a subfield of the underlying pointer,
// and so is also properly aligned, dereferenceable, and all of its
// bytes are initialized.
unsafe { Place::from_field_unchecked(*self, ptr) }
}
}