@@ -5,8 +5,11 @@ use core::{
55 mem:: { align_of, align_of_val, size_of, size_of_val} ,
66 ptr:: NonNull ,
77} ;
8+ use crate :: helpers:: dangling_nonnull;
89
910/// The maximum value of a `usize` with no high bit.
11+ ///
12+ /// Equivalent to `usize::MAX >> 1` or `isize::MAX as usize`.
1013pub const USIZE_MAX_NO_HIGH_BIT : usize = usize:: MAX >> 1 ;
1114
1215/// A trait containing constants for sized types.
@@ -37,7 +40,7 @@ pub trait PtrProps<T: ?Sized> {
3740 /// # Safety
3841 ///
3942 /// The pointer must be valid as a reference.
40- unsafe fn size ( & self ) -> usize ;
43+ unsafe fn size ( & self ) -> usize ;
4144 /// Gets the alignment of the value.
4245 ///
4346 /// # Safety
@@ -49,7 +52,10 @@ pub trait PtrProps<T: ?Sized> {
4952 /// # Safety
5053 ///
5154 /// The pointer must be valid as a reference.
52- unsafe fn layout ( & self ) -> Layout ;
55+ #[ inline]
56+ unsafe fn layout ( & self ) -> Layout {
57+ Layout :: from_size_align_unchecked ( self . size ( ) , self . align ( ) )
58+ }
5359
5460 #[ cfg( feature = "metadata" ) ]
5561 /// Gets the metadata of the value.
@@ -82,51 +88,91 @@ pub trait PtrProps<T: ?Sized> {
8288 }
8389}
8490
85- /// Implements [`PtrProps`] for a pointer type.
86- macro_rules! impl_ptr_props {
87- ( $( $name: ty $( , $to_ptr: ident) ?) * ) => {
88- $(
89- impl <T : ?Sized > PtrProps <T > for $name {
90- unsafe fn size( & self ) -> usize {
91- // We use &*(*val) (?.to_ptr()?) to convert any primitive pointer type to a
92- // reference.
93- // This is kind of a hack, but it lets us avoid *_of_val_raw, which is unstable.
94- size_of_val:: <T >( & * ( * self ) $( . $to_ptr( ) ) ?)
95- }
96-
97- unsafe fn align( & self ) -> usize {
98- align_of_val:: <T >( & * ( * self ) $( . $to_ptr( ) ) ?)
99- }
100-
101- unsafe fn layout( & self ) -> Layout {
102- Layout :: from_size_align_unchecked(
103- self . size( ) ,
104- self . align( )
105- )
106- }
107-
108- #[ cfg( feature = "metadata" ) ]
109- unsafe fn metadata( & self ) -> <T as core:: ptr:: Pointee >:: Metadata {
110- core:: ptr:: metadata( & * ( * self ) $( . $to_ptr( ) ) ?)
111- }
112- }
113- ) *
114- }
91+ macro_rules! impl_ptr_props_raw {
92+ ( $( $name: ty) ,* $( , ) ?) => {
93+ $(
94+ impl <T : ?Sized > PtrProps <T > for $name {
95+ #[ inline]
96+ unsafe fn size( & self ) -> usize {
97+ size_of_val:: <T >( & * * self )
98+ }
99+ #[ inline]
100+ unsafe fn align( & self ) -> usize {
101+ align_of_val:: <T >( & * * self )
102+ }
103+ #[ cfg( feature = "metadata" ) ]
104+ unsafe fn metadata( & self ) -> <T as core:: ptr:: Pointee >:: Metadata {
105+ core:: ptr:: metadata( & * ( * self ) )
106+ }
107+ }
108+ ) *
109+ } ;
115110}
116111
117- impl_ptr_props ! (
118- * const T
119- * mut T
120-
121- & T
122- & mut T
112+ macro_rules! impl_ptr_props_identity {
113+ ( $( $name: ty) ,* $( , ) ?) => {
114+ $(
115+ impl <T : ?Sized > PtrProps <T > for $name {
116+ #[ inline]
117+ unsafe fn size( & self ) -> usize {
118+ size_of_val:: <T >( * self )
119+ }
120+ #[ inline]
121+ unsafe fn align( & self ) -> usize {
122+ align_of_val:: <T >( * self )
123+ }
124+ #[ cfg( feature = "metadata" ) ]
125+ unsafe fn metadata( & self ) -> <T as core:: ptr:: Pointee >:: Metadata {
126+ core:: ptr:: metadata( * self )
127+ }
128+ }
129+ ) *
130+ } ;
131+ }
123132
124- NonNull <T >, as_ptr
133+ macro_rules! impl_ptr_props_as_ref {
134+ ( $( $name: ty) ,* $( , ) ?) => {
135+ $(
136+ impl <T : ?Sized > PtrProps <T > for $name {
137+ #[ inline]
138+ unsafe fn size( & self ) -> usize {
139+ size_of_val:: <T >( self . as_ref( ) )
140+ }
141+ #[ inline]
142+ unsafe fn align( & self ) -> usize {
143+ align_of_val:: <T >( self . as_ref( ) )
144+ }
145+ #[ cfg( feature = "metadata" ) ]
146+ unsafe fn metadata( & self ) -> <T as core:: ptr:: Pointee >:: Metadata {
147+ core:: ptr:: metadata( self . as_ref( ) )
148+ }
149+ }
150+ ) *
151+ } ;
152+ }
125153
126- alloc:: boxed:: Box <T >
127- alloc:: rc:: Rc <T >
154+ impl_ptr_props_raw ! { * const T , * mut T }
155+ impl_ptr_props_identity ! { & T , & mut T }
156+ impl_ptr_props_as_ref ! {
157+ alloc:: boxed:: Box <T >,
158+ alloc:: rc:: Rc <T >,
128159 alloc:: sync:: Arc <T >
129- ) ;
160+ }
161+
162+ impl < T : ?Sized > PtrProps < T > for NonNull < T > {
163+ #[ inline]
164+ unsafe fn size ( & self ) -> usize {
165+ size_of_val :: < T > ( & * self . as_ptr ( ) )
166+ }
167+ #[ inline]
168+ unsafe fn align ( & self ) -> usize {
169+ align_of_val :: < T > ( & * self . as_ptr ( ) )
170+ }
171+ #[ cfg( feature = "metadata" ) ]
172+ unsafe fn metadata ( & self ) -> <T as core:: ptr:: Pointee >:: Metadata {
173+ core:: ptr:: metadata ( & * self . as_ptr ( ) )
174+ }
175+ }
130176
131177#[ cfg( not( feature = "metadata" ) ) ]
132178/// Trait for unsized types whose metadata is `usize` (e.g., slices, `str`).
@@ -152,6 +198,10 @@ pub unsafe trait VarSized: core::ptr::Pointee<Metadata = usize> {
152198 const ALIGN : usize ;
153199}
154200
201+ unsafe impl < T > VarSized for [ T ] {
202+ const ALIGN : usize = T :: ALIGN ;
203+ }
204+
155205unsafe impl VarSized for str {
156206 const ALIGN : usize = u8:: ALIGN ;
157207}
@@ -161,7 +211,7 @@ unsafe impl VarSized for core::ffi::CStr {
161211 const ALIGN : usize = u8:: ALIGN ;
162212}
163213#[ cfg( feature = "std" ) ]
164- // `OsStr == [u8]` and `[u8]: UnsizedCopy `
214+ // `OsStr == [u8]` and `[u8]: VarSized `
165215unsafe impl VarSized for std:: ffi:: OsStr {
166216 const ALIGN : usize = u8:: ALIGN ;
167217}
@@ -171,16 +221,39 @@ unsafe impl VarSized for std::path::Path {
171221 const ALIGN : usize = u8:: ALIGN ;
172222}
173223
174- unsafe impl < T > VarSized for [ T ] {
175- const ALIGN : usize = T :: ALIGN ;
176- }
177-
178224// not associated to reduce clutter, and so they can be const
179225
180- #[ cfg( feature = "metadata" ) ]
181226/// Creates a dangling, zero-length, [`NonNull`] pointer with the proper alignment.
182227#[ must_use]
183228pub const fn varsized_dangling_nonnull < T : ?Sized + VarSized > ( ) -> NonNull < T > {
184- // SAFETY: `ALIGN` is guaranteed to be a valid alignment for `Self`.
185- unsafe { NonNull :: from_raw_parts ( crate :: helpers:: dangling_nonnull ( T :: ALIGN ) , 0 ) }
229+ varsized_nonnull_from_raw_parts ( unsafe { dangling_nonnull ( T :: ALIGN ) } , 0 )
230+ }
231+
232+ #[ must_use]
233+ pub const fn varsized_dangling_pointer < T : ?Sized + VarSized > ( ) -> * mut T {
234+ varsized_pointer_from_raw_parts ( unsafe { dangling_nonnull ( T :: ALIGN ) . as_ptr ( ) } , 0 )
235+ }
236+
237+ /// Creates a `NonNull<T>` from a pointer and a `usize` size metadata.
238+ #[ must_use]
239+ #[ inline]
240+ pub const fn varsized_nonnull_from_raw_parts < T : ?Sized + VarSized > (
241+ p : NonNull < u8 > ,
242+ meta : usize ,
243+ ) -> NonNull < T > {
244+ unsafe { NonNull :: new_unchecked ( varsized_pointer_from_raw_parts ( p. as_ptr ( ) , meta) ) }
245+ }
246+
247+ /// Creates a `*mut T` from a pointer and a `usize` size metadata.
248+ #[ must_use]
249+ #[ inline]
250+ pub const fn varsized_pointer_from_raw_parts < T : ?Sized + VarSized > (
251+ p : * mut u8 ,
252+ meta : usize ,
253+ ) -> * mut T {
254+ // SAFETY: VarSized trait requires T::Metadata == usize
255+ unsafe {
256+ // i hate this so much
257+ * ( ( & ( p, meta) ) as * const ( * mut u8 , usize ) ) . cast :: < * mut T > ( )
258+ }
186259}
0 commit comments