memapi2/data/
type_props.rs1use {
2 crate::helpers::dangling_nonnull,
3 core::{
4 alloc::Layout,
5 mem::{align_of, align_of_val, size_of, size_of_val},
6 ptr::NonNull
7 }
8};
9
10pub const USIZE_MAX_NO_HIGH_BIT: usize = usize::MAX >> 1;
14
15pub const USIZE_HIGH_BIT: usize = usize::MAX ^ (usize::MAX >> 1);
19
20#[must_use]
22#[inline]
23pub const fn usize_bit(bit: u8) -> usize {
24 USIZE_HIGH_BIT >> bit
25}
26
27pub trait SizedProps: Sized {
29 const SZ: usize = size_of::<Self>();
31 const ALN: usize = align_of::<Self>();
33 const LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(Self::SZ, Self::ALN) };
36
37 const IS_ZST: bool = Self::SZ == 0;
39
40 const MAX_SLICE_LEN: usize = match Self::SZ {
42 0 => usize::MAX,
43 sz => USIZE_MAX_NO_HIGH_BIT / sz
44 };
45}
46
47impl<T> SizedProps for T {}
48
49pub trait PtrProps<T: ?Sized> {
51 unsafe fn sz(&self) -> usize;
62 unsafe fn aln(&self) -> usize;
73 #[inline]
84 unsafe fn layout(&self) -> Layout {
85 Layout::from_size_align_unchecked(self.sz(), self.aln())
86 }
87
88 #[cfg(feature = "metadata")]
89 unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata;
100
101 unsafe fn is_zst(&self) -> bool {
112 self.sz() == 0
113 }
114
115 unsafe fn max_slice_len(&self) -> usize {
126 match self.sz() {
127 0 => usize::MAX,
128 sz => USIZE_MAX_NO_HIGH_BIT / sz
129 }
130 }
131}
132
133macro_rules! impl_ptr_props_raw {
134 ($($name:ty),* $(,)?) => {
135 $(
136 impl<T: ?Sized> PtrProps<T> for $name {
137 #[inline]
138 unsafe fn sz(&self) -> usize {
139 size_of_val::<T>(&**self)
140 }
141 #[inline]
142 unsafe fn aln(&self) -> usize {
143 align_of_val::<T>(&**self)
144 }
145 #[cfg(feature = "metadata")]
146 unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
147 core::ptr::metadata(&*(*self))
148 }
149 }
150 )*
151 };
152}
153
154macro_rules! impl_ptr_props_identity {
155 ($($name:ty),* $(,)?) => {
156 $(
157 impl<T: ?Sized> PtrProps<T> for $name {
158 #[inline]
159 unsafe fn sz(&self) -> usize {
160 size_of_val::<T>(*self)
161 }
162 #[inline]
163 unsafe fn aln(&self) -> usize {
164 align_of_val::<T>(*self)
165 }
166 #[cfg(feature = "metadata")]
167 unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
168 core::ptr::metadata(*self)
169 }
170 }
171 )*
172 };
173}
174
175macro_rules! impl_ptr_props_as_ref {
176 ($($name:ty),* $(,)?) => {
177 $(
178 impl<T: ?Sized> PtrProps<T> for $name {
179 #[inline]
180 unsafe fn sz(&self) -> usize {
181 size_of_val::<T>(self.as_ref())
182 }
183 #[inline]
184 unsafe fn aln(&self) -> usize {
185 align_of_val::<T>(self.as_ref())
186 }
187 #[cfg(feature = "metadata")]
188 unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
189 core::ptr::metadata(self.as_ref())
190 }
191 }
192 )*
193 };
194}
195
196impl_ptr_props_raw! { *const T, *mut T }
197impl_ptr_props_identity! { &T, &mut T }
198impl_ptr_props_as_ref! {
199 alloc::boxed::Box<T>,
200 alloc::rc::Rc<T>,
201 alloc::sync::Arc<T>
202}
203
204impl<T: ?Sized> PtrProps<T> for NonNull<T> {
205 #[inline]
206 unsafe fn sz(&self) -> usize {
207 size_of_val::<T>(&*self.as_ptr())
208 }
209
210 #[inline]
211 unsafe fn aln(&self) -> usize {
212 align_of_val::<T>(&*self.as_ptr())
213 }
214
215 #[cfg(feature = "metadata")]
216 unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
217 core::ptr::metadata(&*self.as_ptr())
218 }
219}
220
221#[cfg(not(feature = "metadata"))]
222pub unsafe trait VarSized {
230 type Subtype: Sized + SizedProps;
235
236 const ALN: usize = Self::Subtype::ALN;
241}
242
243#[cfg(feature = "metadata")]
244pub unsafe trait VarSized: core::ptr::Pointee<Metadata = usize> {
251 type Subtype: Sized + SizedProps;
256
257 const ALN: usize = Self::Subtype::ALN;
262}
263
264unsafe impl<T> VarSized for [T] {
266 type Subtype = T;
267}
268
269unsafe impl VarSized for str {
271 type Subtype = u8;
272}
273
274#[cfg(feature = "c_str")]
275unsafe impl VarSized for core::ffi::CStr {
277 type Subtype = u8;
278}
279#[cfg(feature = "std")]
280unsafe impl VarSized for std::ffi::OsStr {
282 type Subtype = u8;
283}
284
285#[cfg(feature = "std")]
286unsafe impl VarSized for std::path::Path {
288 type Subtype = u8;
289}
290
291const_if! {
294 "const_extras",
295 "Creates a dangling, zero-length, [`NonNull`] pointer with the proper alignment.",
296 #[must_use]
297 pub const fn varsized_dangling_nonnull<T: ?Sized + VarSized>() -> NonNull<T> {
298 varsized_nonnull_from_raw_parts(unsafe { dangling_nonnull(T::ALN) }, 0)
300 }
301}
302
303const_if! {
304 "const_extras",
305 "Creates a dangling, zero-length [`NonNull`] pointer with the proper alignment.",
306 #[must_use]
307 pub const fn varsized_dangling_pointer<T: ?Sized + VarSized>() -> *mut T {
308 varsized_pointer_from_raw_parts(unsafe { dangling_nonnull(T::ALN).as_ptr() }, 0)
310 }
311}
312
313const_if! {
314 "const_extras",
315 "Creates a `NonNull<T>` from a pointer and a `usize` size metadata.",
316 #[must_use]
317 #[inline]
318 pub const fn varsized_nonnull_from_raw_parts<T: ?Sized + VarSized>(
319 p: NonNull<u8>,
320 meta: usize,
321 ) -> NonNull<T> {
322 unsafe { NonNull::new_unchecked(varsized_pointer_from_raw_parts(p.as_ptr(), meta)) }
324 }
325}
326
327const_if! {
328 "const_extras",
329 "Creates a `*mut T` from a pointer and a `usize` size metadata.",
330 #[must_use]
331 #[inline]
332 pub const fn varsized_pointer_from_raw_parts<T: ?Sized + VarSized>(
333 p: *mut u8,
334 meta: usize,
335 ) -> *mut T {
336 unsafe {
338 *((&(p, meta)) as *const (*mut u8, usize)).cast::<*mut T>()
340 }
341 }
342}