memapi2/data/
type_props.rs1use {
2 crate::{Layout, helpers::dangling_nonnull},
3 core::{
4 mem::{align_of, align_of_val, size_of, size_of_val},
5 ptr::NonNull
6 }
7};
8
9pub const USIZE_MAX_NO_HIGH_BIT: usize = usize::MAX >> 1;
13
14pub const USIZE_HIGH_BIT: usize = usize::MAX ^ (usize::MAX >> 1);
18
19#[must_use]
21#[inline]
22pub const fn usize_bit(bit: u8) -> usize { USIZE_HIGH_BIT >> bit }
23
24pub trait SizedProps: Sized {
26 const SZ: usize = size_of::<Self>();
28 const ALN: usize = align_of::<Self>();
30 const LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(Self::SZ, Self::ALN) };
33
34 const IS_ZST: bool = Self::SZ == 0;
36
37 const MAX_SLICE_LEN: usize = match Self::SZ {
39 0 => usize::MAX,
40 sz => USIZE_MAX_NO_HIGH_BIT / sz
41 };
42}
43
44impl<T> SizedProps for T {}
45
46pub trait PtrProps<T: ?Sized> {
48 unsafe fn sz(&self) -> usize;
59 unsafe fn aln(&self) -> usize;
70 #[inline]
81 unsafe fn layout(&self) -> Layout { Layout::from_size_align_unchecked(self.sz(), self.aln()) }
82
83 #[cfg(feature = "metadata")]
84 unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata;
95
96 unsafe fn is_zst(&self) -> bool { self.sz() == 0 }
107
108 unsafe fn max_slice_len(&self) -> usize {
119 match self.sz() {
120 0 => usize::MAX,
121 sz => USIZE_MAX_NO_HIGH_BIT / sz
122 }
123 }
124}
125
126macro_rules! impl_ptr_props_raw {
127 ($($name:ty),* $(,)?) => {
128 $(
129 impl<T: ?Sized> PtrProps<T> for $name {
130 #[inline]
131 unsafe fn sz(&self) -> usize {
132 size_of_val::<T>(&**self)
133 }
134 #[inline]
135 unsafe fn aln(&self) -> usize {
136 align_of_val::<T>(&**self)
137 }
138 #[cfg(feature = "metadata")]
139 unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
140 core::ptr::metadata(&*(*self))
141 }
142 }
143 )*
144 };
145}
146
147macro_rules! impl_ptr_props_identity {
148 ($($name:ty),* $(,)?) => {
149 $(
150 impl<T: ?Sized> PtrProps<T> for $name {
151 #[inline]
152 unsafe fn sz(&self) -> usize {
153 size_of_val::<T>(*self)
154 }
155 #[inline]
156 unsafe fn aln(&self) -> usize {
157 align_of_val::<T>(*self)
158 }
159 #[cfg(feature = "metadata")]
160 unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
161 core::ptr::metadata(*self)
162 }
163 }
164 )*
165 };
166}
167
168macro_rules! impl_ptr_props_as_ref {
169 ($($name:ty),* $(,)?) => {
170 $(
171 impl<T: ?Sized> PtrProps<T> for $name {
172 #[inline]
173 unsafe fn sz(&self) -> usize {
174 size_of_val::<T>(self.as_ref())
175 }
176 #[inline]
177 unsafe fn aln(&self) -> usize {
178 align_of_val::<T>(self.as_ref())
179 }
180 #[cfg(feature = "metadata")]
181 unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
182 core::ptr::metadata(self.as_ref())
183 }
184 }
185 )*
186 };
187}
188
189impl_ptr_props_raw! { *const T, *mut T }
190impl_ptr_props_identity! { &T, &mut T }
191impl_ptr_props_as_ref! {
192 alloc::boxed::Box<T>,
193 alloc::rc::Rc<T>,
194 alloc::sync::Arc<T>
195}
196
197impl<T: ?Sized> PtrProps<T> for NonNull<T> {
198 #[inline]
199 unsafe fn sz(&self) -> usize { size_of_val::<T>(&*self.as_ptr()) }
200
201 #[inline]
202 unsafe fn aln(&self) -> usize { align_of_val::<T>(&*self.as_ptr()) }
203
204 #[cfg(feature = "metadata")]
205 unsafe fn metadata(&self) -> <T as core::ptr::Pointee>::Metadata {
206 core::ptr::metadata(&*self.as_ptr())
207 }
208}
209
210#[cfg(not(feature = "metadata"))]
211pub unsafe trait VarSized {
219 type Subtype: Sized + SizedProps;
224
225 const ALN: usize = Self::Subtype::ALN;
230}
231
232#[cfg(feature = "metadata")]
233pub unsafe trait VarSized: core::ptr::Pointee<Metadata = usize> {
240 type Subtype: Sized + SizedProps;
245
246 const ALN: usize = Self::Subtype::ALN;
251}
252
253unsafe impl<T> VarSized for [T] {
255 type Subtype = T;
256}
257
258unsafe impl VarSized for str {
260 type Subtype = u8;
261}
262
263#[cfg(feature = "c_str")]
264unsafe impl VarSized for core::ffi::CStr {
266 type Subtype = u8;
267}
268#[cfg(feature = "std")]
269unsafe impl VarSized for std::ffi::OsStr {
271 type Subtype = u8;
272}
273
274#[cfg(feature = "std")]
275unsafe impl VarSized for std::path::Path {
277 type Subtype = u8;
278}
279
280const_if! {
283 "const_extras",
284 "Creates a dangling, zero-length, [`NonNull`] pointer with the proper alignment.",
285 #[must_use]
286 pub const fn varsized_dangling_nonnull<T: ?Sized + VarSized>() -> NonNull<T> {
287 varsized_nonnull_from_raw_parts(unsafe { dangling_nonnull(T::ALN) }, 0)
289 }
290}
291
292const_if! {
293 "const_extras",
294 "Creates a dangling, zero-length [`NonNull`] pointer with the proper alignment.",
295 #[must_use]
296 pub const fn varsized_dangling_pointer<T: ?Sized + VarSized>() -> *mut T {
297 varsized_pointer_from_raw_parts(unsafe { dangling_nonnull(T::ALN).as_ptr() }, 0)
299 }
300}
301
302const_if! {
303 "const_extras",
304 "Creates a `NonNull<T>` from a pointer and a `usize` size metadata.",
305 #[must_use]
306 #[inline]
307 pub const fn varsized_nonnull_from_raw_parts<T: ?Sized + VarSized>(
308 p: NonNull<u8>,
309 meta: usize,
310 ) -> NonNull<T> {
311 unsafe { NonNull::new_unchecked(varsized_pointer_from_raw_parts(p.as_ptr(), meta)) }
313 }
314}
315
316const_if! {
317 "const_extras",
318 "Creates a `*mut T` from a pointer and a `usize` size metadata.",
319 #[must_use]
320 #[inline]
321 pub const fn varsized_pointer_from_raw_parts<T: ?Sized + VarSized>(
322 p: *mut u8,
323 meta: usize,
324 ) -> *mut T {
325 unsafe {
327 *((&(p, meta)) as *const (*mut u8, usize)).cast::<*mut T>()
329 }
330 }
331}