@@ -7,17 +7,37 @@ use core::{
7
7
cell:: UnsafeCell , marker:: PhantomData , mem:: ManuallyDrop , num:: NonZeroUsize , ptr:: NonNull ,
8
8
} ;
9
9
10
+ #[ derive( Copy , Clone ) ]
11
+ /// Used as a type argument to [`Ptr`], [`PtrMut`] and [`OwningPtr`] to specify that the pointer is aligned.
12
+ pub struct Aligned ;
13
+ #[ derive( Copy , Clone ) ]
14
+ /// Used as a type argument to [`Ptr`], [`PtrMut`] and [`OwningPtr`] to specify that the pointer is not aligned.
15
+ pub struct Unaligned ;
16
+
17
+ /// Trait that is only implemented for [`Aligned`] and [`Unaligned`] to work around the lack of ability
18
+ /// to have const generics of an enum.
19
+ pub trait IsAligned : sealed:: Sealed { }
20
+ impl IsAligned for Aligned { }
21
+ impl IsAligned for Unaligned { }
22
+
23
+ mod sealed {
24
+ pub trait Sealed { }
25
+ impl Sealed for super :: Aligned { }
26
+ impl Sealed for super :: Unaligned { }
27
+ }
28
+
10
29
/// Type-erased borrow of some unknown type chosen when constructing this type.
11
30
///
12
31
/// This type tries to act "borrow-like" which means that:
13
32
/// - It should be considered immutable: its target must not be changed while this pointer is alive.
14
33
/// - It must always points to a valid value of whatever the pointee type is.
15
34
/// - The lifetime `'a` accurately represents how long the pointer is valid for.
35
+ /// - Must be sufficiently aligned for the unknown pointee type.
16
36
///
17
37
/// It may be helpful to think of this type as similar to `&'a dyn Any` but without
18
38
/// the metadata and able to point to data that does not correspond to a Rust type.
19
39
#[ derive( Copy , Clone ) ]
20
- pub struct Ptr < ' a > ( NonNull < u8 > , PhantomData < & ' a u8 > ) ;
40
+ pub struct Ptr < ' a , A : IsAligned = Aligned > ( NonNull < u8 > , PhantomData < ( & ' a u8 , A ) > ) ;
21
41
22
42
/// Type-erased mutable borrow of some unknown type chosen when constructing this type.
23
43
///
@@ -26,10 +46,11 @@ pub struct Ptr<'a>(NonNull<u8>, PhantomData<&'a u8>);
26
46
/// aliased mutability.
27
47
/// - It must always points to a valid value of whatever the pointee type is.
28
48
/// - The lifetime `'a` accurately represents how long the pointer is valid for.
49
+ /// - Must be sufficiently aligned for the unknown pointee type.
29
50
///
30
51
/// It may be helpful to think of this type as similar to `&'a mut dyn Any` but without
31
52
/// the metadata and able to point to data that does not correspond to a Rust type.
32
- pub struct PtrMut < ' a > ( NonNull < u8 > , PhantomData < & ' a mut u8 > ) ;
53
+ pub struct PtrMut < ' a , A : IsAligned = Aligned > ( NonNull < u8 > , PhantomData < ( & ' a mut u8 , A ) > ) ;
33
54
34
55
/// Type-erased Box-like pointer to some unknown type chosen when constructing this type.
35
56
/// Conceptually represents ownership of whatever data is being pointed to and so is
@@ -42,22 +63,32 @@ pub struct PtrMut<'a>(NonNull<u8>, PhantomData<&'a mut u8>);
42
63
/// to aliased mutability and potentially use after free bugs.
43
64
/// - It must always points to a valid value of whatever the pointee type is.
44
65
/// - The lifetime `'a` accurately represents how long the pointer is valid for.
66
+ /// - Must be sufficiently aligned for the unknown pointee type.
45
67
///
46
68
/// It may be helpful to think of this type as similar to `&'a mut ManuallyDrop<dyn Any>` but
47
69
/// without the metadata and able to point to data that does not correspond to a Rust type.
48
- pub struct OwningPtr < ' a > ( NonNull < u8 > , PhantomData < & ' a mut u8 > ) ;
70
+ pub struct OwningPtr < ' a , A : IsAligned = Aligned > ( NonNull < u8 > , PhantomData < ( & ' a mut u8 , A ) > ) ;
49
71
50
72
macro_rules! impl_ptr {
51
73
( $ptr: ident) => {
52
- impl $ptr<' _> {
74
+ impl <' a> $ptr<' a, Aligned > {
75
+ /// Removes the alignment requirement of this pointer
76
+ pub fn to_unaligned( self ) -> $ptr<' a, Unaligned > {
77
+ $ptr( self . 0 , PhantomData )
78
+ }
79
+ }
80
+
81
+ impl <A : IsAligned > $ptr<' _, A > {
53
82
/// Calculates the offset from a pointer.
54
83
/// As the pointer is type-erased, there is no size information available. The provided
55
84
/// `count` parameter is in raw bytes.
56
85
///
57
86
/// *See also: [`ptr::offset`][ptr_offset]*
58
87
///
59
88
/// # Safety
60
- /// the offset cannot make the existing ptr null, or take it out of bounds for its allocation.
89
+ /// - The offset cannot make the existing ptr null, or take it out of bounds for its allocation.
90
+ /// - If the `A` type parameter is [`Aligned`] then the offset must not make the resulting pointer
91
+ /// be unaligned for the pointee type.
61
92
///
62
93
/// [ptr_offset]: https://doc.rust-lang.org/std/primitive.pointer.html#method.offset
63
94
#[ inline]
@@ -75,7 +106,9 @@ macro_rules! impl_ptr {
75
106
/// *See also: [`ptr::add`][ptr_add]*
76
107
///
77
108
/// # Safety
78
- /// the offset cannot make the existing ptr null, or take it out of bounds for its allocation.
109
+ /// - The offset cannot make the existing ptr null, or take it out of bounds for its allocation.
110
+ /// - If the `A` type parameter is [`Aligned`] then the offset must not make the resulting pointer
111
+ /// be unaligned for the pointee type.
79
112
///
80
113
/// [ptr_add]: https://doc.rust-lang.org/std/primitive.pointer.html#method.add
81
114
#[ inline]
@@ -85,18 +118,9 @@ macro_rules! impl_ptr {
85
118
PhantomData ,
86
119
)
87
120
}
88
-
89
- /// Creates a new instance from a raw pointer.
90
- ///
91
- /// # Safety
92
- /// The lifetime for the returned item must not exceed the lifetime `inner` is valid for
93
- #[ inline]
94
- pub unsafe fn new( inner: NonNull <u8 >) -> Self {
95
- Self ( inner, PhantomData )
96
- }
97
121
}
98
122
99
- impl Pointer for $ptr<' _> {
123
+ impl < A : IsAligned > Pointer for $ptr<' _, A > {
100
124
#[ inline]
101
125
fn fmt( & self , f: & mut Formatter <' _>) -> fmt:: Result {
102
126
Pointer :: fmt( & self . 0 , f)
@@ -109,20 +133,35 @@ impl_ptr!(Ptr);
109
133
impl_ptr ! ( PtrMut ) ;
110
134
impl_ptr ! ( OwningPtr ) ;
111
135
112
- impl < ' a > Ptr < ' a > {
136
+ impl < ' a , A : IsAligned > Ptr < ' a , A > {
137
+ /// Creates a new instance from a raw pointer.
138
+ ///
139
+ /// # Safety
140
+ /// - `inner` must point to valid value of whatever the pointee type is.
141
+ /// - If the `A` type parameter is [`Aligned`] then `inner` must be sufficiently aligned for the pointee type.
142
+ /// - `inner` must have correct provenance to allow reads of the pointee type.
143
+ /// - The lifetime `'a` must be constrained such that this [`Ptr`] will stay valid and nothing
144
+ /// can mutate the pointee while this [`Ptr`] is live except through an `UnsafeCell`.
145
+ #[ inline]
146
+ pub unsafe fn new ( inner : NonNull < u8 > ) -> Self {
147
+ Self ( inner, PhantomData )
148
+ }
149
+
113
150
/// Transforms this [`Ptr`] into an [`PtrMut`]
114
151
///
115
152
/// # Safety
116
153
/// Another [`PtrMut`] for the same [`Ptr`] must not be created until the first is dropped.
117
154
#[ inline]
118
- pub unsafe fn assert_unique ( self ) -> PtrMut < ' a > {
155
+ pub unsafe fn assert_unique ( self ) -> PtrMut < ' a , A > {
119
156
PtrMut ( self . 0 , PhantomData )
120
157
}
121
158
122
159
/// Transforms this [`Ptr<T>`] into a `&T` with the same lifetime
123
160
///
124
161
/// # Safety
125
- /// Must point to a valid `T`
162
+ /// - `T` must be the erased pointee type for this [`Ptr`].
163
+ /// - If the type parameter `A` is `Unaligned` then this pointer must be sufficiently aligned
164
+ /// for the pointee type `T`.
126
165
#[ inline]
127
166
pub unsafe fn deref < T > ( self ) -> & ' a T {
128
167
& * self . as_ptr ( ) . cast ( )
@@ -148,20 +187,35 @@ impl<'a, T> From<&'a T> for Ptr<'a> {
148
187
}
149
188
}
150
189
151
- impl < ' a > PtrMut < ' a > {
190
+ impl < ' a , A : IsAligned > PtrMut < ' a , A > {
191
+ /// Creates a new instance from a raw pointer.
192
+ ///
193
+ /// # Safety
194
+ /// - `inner` must point to valid value of whatever the pointee type is.
195
+ /// - If the `A` type parameter is [`Aligned`] then `inner` must be sufficiently aligned for the pointee type.
196
+ /// - `inner` must have correct provenance to allow read and writes of the pointee type.
197
+ /// - The lifetime `'a` must be constrained such that this [`PtrMut`] will stay valid and nothing
198
+ /// else can read or mutate the pointee while this [`PtrMut`] is live.
199
+ #[ inline]
200
+ pub unsafe fn new ( inner : NonNull < u8 > ) -> Self {
201
+ Self ( inner, PhantomData )
202
+ }
203
+
152
204
/// Transforms this [`PtrMut`] into an [`OwningPtr`]
153
205
///
154
206
/// # Safety
155
207
/// Must have right to drop or move out of [`PtrMut`].
156
208
#[ inline]
157
- pub unsafe fn promote ( self ) -> OwningPtr < ' a > {
209
+ pub unsafe fn promote ( self ) -> OwningPtr < ' a , A > {
158
210
OwningPtr ( self . 0 , PhantomData )
159
211
}
160
212
161
213
/// Transforms this [`PtrMut<T>`] into a `&mut T` with the same lifetime
162
214
///
163
215
/// # Safety
164
- /// Must point to a valid `T`
216
+ /// - `T` must be the erased pointee type for this [`PtrMut`].
217
+ /// - If the type parameter `A` is [`Unaligned`] then this pointer must be sufficiently aligned
218
+ /// for the pointee type `T`.
165
219
#[ inline]
166
220
pub unsafe fn deref_mut < T > ( self ) -> & ' a mut T {
167
221
& mut * self . as_ptr ( ) . cast ( )
@@ -177,16 +231,16 @@ impl<'a> PtrMut<'a> {
177
231
self . 0 . as_ptr ( )
178
232
}
179
233
180
- /// Gets a `PtrMut` from this with a smaller lifetime.
234
+ /// Gets a [ `PtrMut`] from this with a smaller lifetime.
181
235
#[ inline]
182
- pub fn reborrow ( & mut self ) -> PtrMut < ' _ > {
236
+ pub fn reborrow ( & mut self ) -> PtrMut < ' _ , A > {
183
237
// SAFE: the ptrmut we're borrowing from is assumed to be valid
184
238
unsafe { PtrMut :: new ( self . 0 ) }
185
239
}
186
240
187
241
/// Gets an immutable reference from this mutable reference
188
242
#[ inline]
189
- pub fn as_ref ( & self ) -> Ptr < ' _ > {
243
+ pub fn as_ref ( & self ) -> Ptr < ' _ , A > {
190
244
// SAFE: The `PtrMut` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
191
245
unsafe { Ptr :: new ( self . 0 ) }
192
246
}
@@ -210,11 +264,27 @@ impl<'a> OwningPtr<'a> {
210
264
// so it's safe to promote it to an owning pointer.
211
265
f ( unsafe { PtrMut :: from ( & mut * temp) . promote ( ) } )
212
266
}
267
+ }
268
+ impl < ' a , A : IsAligned > OwningPtr < ' a , A > {
269
+ /// Creates a new instance from a raw pointer.
270
+ ///
271
+ /// # Safety
272
+ /// - `inner` must point to valid value of whatever the pointee type is.
273
+ /// - If the `A` type parameter is [`Aligned`] then `inner` must be sufficiently aligned for the pointee type.
274
+ /// - `inner` must have correct provenance to allow read and writes of the pointee type.
275
+ /// - The lifetime `'a` must be constrained such that this [`OwningPtr`] will stay valid and nothing
276
+ /// else can read or mutate the pointee while this [`OwningPtr`] is live.
277
+ #[ inline]
278
+ pub unsafe fn new ( inner : NonNull < u8 > ) -> Self {
279
+ Self ( inner, PhantomData )
280
+ }
213
281
214
282
/// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.
215
283
///
216
284
/// # Safety
217
- /// Must point to a valid `T`.
285
+ /// - `T` must be the erased pointee type for this [`OwningPtr`].
286
+ /// - If the type parameter `A` is `Unaligned` then this pointer must be sufficiently aligned
287
+ /// for the pointee type `T`.
218
288
#[ inline]
219
289
pub unsafe fn read < T > ( self ) -> T {
220
290
self . as_ptr ( ) . cast :: < T > ( ) . read ( )
@@ -223,7 +293,9 @@ impl<'a> OwningPtr<'a> {
223
293
/// Consumes the [`OwningPtr`] to drop the underlying data of type `T`.
224
294
///
225
295
/// # Safety
226
- /// Must point to a valid `T`.
296
+ /// - `T` must be the erased pointee type for this [`OwningPtr`].
297
+ /// - If the type parameter `A` is `Unaligned` then this pointer must be sufficiently aligned
298
+ /// for the pointee type `T`.
227
299
#[ inline]
228
300
pub unsafe fn drop_as < T > ( self ) {
229
301
self . as_ptr ( ) . cast :: < T > ( ) . drop_in_place ( ) ;
@@ -241,14 +313,14 @@ impl<'a> OwningPtr<'a> {
241
313
242
314
/// Gets an immutable pointer from this owned pointer.
243
315
#[ inline]
244
- pub fn as_ref ( & self ) -> Ptr < ' _ > {
316
+ pub fn as_ref ( & self ) -> Ptr < ' _ , A > {
245
317
// SAFE: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
246
318
unsafe { Ptr :: new ( self . 0 ) }
247
319
}
248
320
249
321
/// Gets a mutable pointer from this owned pointer.
250
322
#[ inline]
251
- pub fn as_mut ( & mut self ) -> PtrMut < ' _ > {
323
+ pub fn as_mut ( & mut self ) -> PtrMut < ' _ , A > {
252
324
// SAFE: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
253
325
unsafe { PtrMut :: new ( self . 0 ) }
254
326
}
0 commit comments