nstd_sys/core/ptr.rs
1//! A sized pointer to some arbitrary type.
2use crate::{
3 core::{
4 mem::{nstd_core_mem_copy, nstd_core_mem_is_aligned},
5 optional::{gen_optional, NSTDOptional},
6 },
7 NSTDAny, NSTDAnyMut, NSTDUInt, NSTD_INT_MAX,
8};
9use nstdapi::nstdapi;
10
11/// A sized immutable pointer to some arbitrary type.
12#[nstdapi]
13#[derive(Clone, Copy)]
14pub struct NSTDPtr {
15 /// A raw pointer to the data.
16 raw: NSTDAny,
17 /// The size of the object being pointed to.
18 size: NSTDUInt,
19 /// The alignment of the object being pointed to.
20 align: NSTDUInt,
21}
22gen_optional!(NSTDOptionalPtr, NSTDPtr);
23
24/// Creates a new instance of `NSTDPtr`.
25///
26/// # Parameters:
27///
28/// - `NSTDAny obj` - The object to point to.
29///
30/// - `NSTDUInt size` - The number of bytes that `obj`'s type occupies.
31///
32/// - `NSTDUInt align` - The alignment of the object that `obj` points to.
33///
34/// # Returns
35///
36/// `NSTDOptionalPtr ptr` - A new instance of `NSTDPtr` that points to `obj` on success, or
37/// an uninitialized "none" variant if `obj` is null or unaligned or if `size` is greater than
38/// `NSTDInt`'s max value.
39///
40/// # Panics
41///
42/// This operation will panic if `align` is not a power of two.
43#[inline]
44#[nstdapi]
45pub fn nstd_core_ptr_new(obj: NSTDAny, size: NSTDUInt, align: NSTDUInt) -> NSTDOptionalPtr {
46 match !obj.is_null() && nstd_core_mem_is_aligned(obj, align) && size <= NSTD_INT_MAX {
47 true => NSTDOptional::Some(NSTDPtr {
48 raw: obj,
49 size,
50 align,
51 }),
52 false => NSTDOptional::None,
53 }
54}
55
56/// Creates a new instance of `NSTDPtr` without checking if `obj` is null.
57///
58/// # Parameters:
59///
60/// - `NSTDAny obj` - The object to point to.
61///
62/// - `NSTDUInt size` - The number of bytes that `obj`'s type occupies.
63///
64/// - `NSTDUInt align` - The alignment of the object that `obj` points to.
65///
66/// # Returns
67///
68/// `NSTDPtr ptr` - A new instance of `NSTDPtr` that points to `obj`.
69///
70/// # Safety
71///
72/// - `obj` must be non-null.
73///
74/// - `obj` must be aligned to `align`.
75///
76/// - `align` must be a nonzero power of two.
77///
78/// - `size` must not be greater than `NSTDInt`'s max value.
79#[inline]
80#[nstdapi]
81pub const unsafe fn nstd_core_ptr_new_unchecked(
82 obj: NSTDAny,
83 size: NSTDUInt,
84 align: NSTDUInt,
85) -> NSTDPtr {
86 NSTDPtr {
87 raw: obj,
88 size,
89 align,
90 }
91}
92
93/// Returns the size of the object being pointed to.
94///
95/// # Parameters:
96///
97/// - `const NSTDPtr *ptr` - The pointer.
98///
99/// # Returns
100///
101/// `NSTDUInt size` - The size of the object pointed to by `ptr`.
102///
103/// # Examples
104///
105/// ```
106/// use core::ptr::addr_of;
107/// use nstd_sys::core::ptr::{nstd_core_ptr_new, nstd_core_ptr_size};
108///
109/// unsafe {
110/// const SIZE: usize = core::mem::size_of::<isize>();
111/// const ALIGN: usize = core::mem::align_of::<isize>();
112/// let x = 33isize;
113/// let ptr = nstd_core_ptr_new(addr_of!(x).cast(), SIZE, ALIGN).unwrap();
114/// assert!(nstd_core_ptr_size(&ptr) == SIZE);
115/// }
116/// ```
117#[inline]
118#[nstdapi]
119pub const fn nstd_core_ptr_size(ptr: &NSTDPtr) -> NSTDUInt {
120 ptr.size
121}
122
123/// Returns the alignment of the object being pointed to.
124///
125/// # Parameters:
126///
127/// - `const NSTDPtr *ptr` - The pointer.
128///
129/// # Returns
130///
131/// `NSTDUInt align` - The alignment of the object pointed to by `ptr`.
132///
133/// # Examples
134///
135/// ```
136/// use core::ptr::addr_of;
137/// use nstd_sys::core::ptr::{nstd_core_ptr_align, nstd_core_ptr_new};
138///
139/// unsafe {
140/// const SIZE: usize = core::mem::size_of::<[u8; 32]>();
141/// const ALIGN: usize = core::mem::align_of::<[u8; 32]>();
142/// let x = [33u8; 32];
143/// let ptr = nstd_core_ptr_new(addr_of!(x).cast(), SIZE, ALIGN).unwrap();
144/// assert!(nstd_core_ptr_align(&ptr) == ALIGN);
145/// }
146/// ```
147#[inline]
148#[nstdapi]
149pub const fn nstd_core_ptr_align(ptr: &NSTDPtr) -> NSTDUInt {
150 ptr.align
151}
152
153/// Returns a raw immutable pointer to the object pointed to by `ptr`.
154///
155/// # Parameters:
156///
157/// - `const NSTDPtr *ptr` - The higher level pointer.
158///
159/// # Returns
160///
161/// `NSTDAny raw` - A raw pointer to the object.
162///
163/// # Examples
164///
165/// ```
166/// use core::ptr::addr_of;
167/// use nstd_sys::core::ptr::{nstd_core_ptr_get, nstd_core_ptr_new};
168///
169/// unsafe {
170/// const SIZE: usize = core::mem::size_of::<u32>();
171/// const ALIGN: usize = core::mem::align_of::<u32>();
172/// let x = 45u32;
173/// let ptr = nstd_core_ptr_new(addr_of!(x).cast(), SIZE, ALIGN).unwrap();
174/// assert!(*nstd_core_ptr_get(&ptr).cast::<u32>() == x);
175/// }
176/// ```
177#[inline]
178#[nstdapi]
179pub const fn nstd_core_ptr_get(ptr: &NSTDPtr) -> NSTDAny {
180 ptr.raw
181}
182
183/// A sized pointer to some arbitrary type.
184#[nstdapi]
185pub struct NSTDPtrMut {
186 /// A raw pointer to the data.
187 raw: NSTDAnyMut,
188 /// The size of the object being pointed to.
189 size: NSTDUInt,
190 /// The alignment of the object being pointed to.
191 align: NSTDUInt,
192}
193gen_optional!(NSTDOptionalPtrMut, NSTDPtrMut);
194
195/// Creates a new instance of `NSTDPtrMut`.
196///
197/// # Parameters:
198///
199/// - `NSTDAnyMut obj` - The object to point to.
200///
201/// - `NSTDUInt size` - The number of bytes that `obj`'s type occupies.
202///
203/// - `NSTDUInt align` - The alignment of the object that `obj` points to.
204///
205/// # Returns
206///
207/// `NSTDOptionalPtrMut ptr` - A new instance of `NSTDPtrMut` that points to `obj` on success, or
208/// an uninitialized "none" variant if `obj` is null or unaligned or if `size` is greater than
209/// `NSTDInt`'s max value.
210///
211/// # Panics
212///
213/// This operation will panic if `align` is not a power of two.
214#[inline]
215#[nstdapi]
216pub fn nstd_core_ptr_mut_new(
217 obj: NSTDAnyMut,
218 size: NSTDUInt,
219 align: NSTDUInt,
220) -> NSTDOptionalPtrMut {
221 match !obj.is_null() && nstd_core_mem_is_aligned(obj, align) && size <= NSTD_INT_MAX {
222 true => NSTDOptional::Some(NSTDPtrMut {
223 raw: obj,
224 size,
225 align,
226 }),
227 false => NSTDOptional::None,
228 }
229}
230
231/// Creates a new instance of `NSTDPtrMut` without checking if `obj` is null.
232///
233/// # Parameters:
234///
235/// - `NSTDAnyMut obj` - The object to point to.
236///
237/// - `NSTDUInt size` - The number of bytes that `obj`'s type occupies.
238///
239/// - `NSTDUInt align` - The alignment of the object that `obj` points to.
240///
241/// # Returns
242///
243/// `NSTDPtrMut ptr` - A new instance of `NSTDPtrMut` that points to `obj`.
244///
245/// # Safety
246///
247/// - `obj` must be non-null.
248///
249/// - `obj` must be aligned to `align`.
250///
251/// - `align` must be a nonzero power of two.
252///
253/// - `size` must not be greater than `NSTDInt`'s max value.
254#[inline]
255#[nstdapi]
256pub const unsafe fn nstd_core_ptr_mut_new_unchecked(
257 obj: NSTDAnyMut,
258 size: NSTDUInt,
259 align: NSTDUInt,
260) -> NSTDPtrMut {
261 NSTDPtrMut {
262 raw: obj,
263 size,
264 align,
265 }
266}
267
268/// Creates an immutable version of a mutable pointer.
269///
270/// # Parameters:
271///
272/// - `const NSTDPtrMut *ptr` - The mutable pointer.
273///
274/// # Returns
275///
276/// `NSTDPtr ptr_const` - The immutable copy of `ptr`.
277#[inline]
278#[nstdapi]
279pub const fn nstd_core_ptr_mut_as_const(ptr: &NSTDPtrMut) -> NSTDPtr {
280 // SAFETY: `ptr.raw` is never null, `ptr.size` is never greater than `NSTDInt`'s max value.
281 unsafe { nstd_core_ptr_new_unchecked(ptr.raw, ptr.size, ptr.align) }
282}
283
284/// Returns the size of the object being pointed to.
285///
286/// # Parameters:
287///
288/// - `const NSTDPtrMut *ptr` - The pointer.
289///
290/// # Returns
291///
292/// `NSTDUInt size` - The size of the object pointed to by `ptr`.
293///
294/// # Examples
295///
296/// ```
297/// use core::ptr::addr_of_mut;
298/// use nstd_sys::core::ptr::{nstd_core_ptr_mut_new, nstd_core_ptr_mut_size};
299///
300/// unsafe {
301/// const SIZE: usize = core::mem::size_of::<isize>();
302/// const ALIGN: usize = core::mem::align_of::<isize>();
303/// let mut x = 33isize;
304/// let ptr = nstd_core_ptr_mut_new(addr_of_mut!(x).cast(), SIZE, ALIGN).unwrap();
305/// assert!(nstd_core_ptr_mut_size(&ptr) == SIZE);
306/// }
307/// ```
308#[inline]
309#[nstdapi]
310pub const fn nstd_core_ptr_mut_size(ptr: &NSTDPtrMut) -> NSTDUInt {
311 ptr.size
312}
313
314/// Returns the alignment of the object being pointed to.
315///
316/// # Parameters:
317///
318/// - `const NSTDPtrMut *ptr` - The pointer.
319///
320/// # Returns
321///
322/// `NSTDUInt align` - The alignment of the object pointed to by `ptr`.
323///
324/// # Examples
325///
326/// ```
327/// use core::ptr::addr_of_mut;
328/// use nstd_sys::core::ptr::{nstd_core_ptr_mut_align, nstd_core_ptr_mut_new};
329///
330/// unsafe {
331/// const SIZE: usize = core::mem::size_of::<[u8; 32]>();
332/// const ALIGN: usize = core::mem::align_of::<[u8; 32]>();
333/// let mut x = [33u8; 32];
334/// let ptr = nstd_core_ptr_mut_new(addr_of_mut!(x).cast(), SIZE, ALIGN).unwrap();
335/// assert!(nstd_core_ptr_mut_align(&ptr) == ALIGN);
336/// }
337/// ```
338#[inline]
339#[nstdapi]
340pub const fn nstd_core_ptr_mut_align(ptr: &NSTDPtrMut) -> NSTDUInt {
341 ptr.align
342}
343
344/// Returns a raw pointer to the object pointed to by `ptr`.
345///
346/// # Parameters:
347///
348/// - `NSTDPtrMut *ptr` - The higher level pointer.
349///
350/// # Returns
351///
352/// `NSTDAnyMut raw` - A raw pointer to the object.
353///
354/// # Examples
355///
356/// ```
357/// use core::ptr::addr_of_mut;
358/// use nstd_sys::core::ptr::{nstd_core_ptr_mut_get, nstd_core_ptr_mut_new};
359///
360/// unsafe {
361/// const SIZE: usize = core::mem::size_of::<u32>();
362/// const ALIGN: usize = core::mem::align_of::<u32>();
363/// let mut x = 8u32;
364/// let mut ptr = nstd_core_ptr_mut_new(addr_of_mut!(x).cast(), SIZE, ALIGN).unwrap();
365/// let x_ptr = nstd_core_ptr_mut_get(&mut ptr).cast();
366/// *x_ptr *= 2;
367/// assert!(x == *x_ptr);
368/// }
369/// ```
370#[inline]
371#[nstdapi]
372pub fn nstd_core_ptr_mut_get(ptr: &mut NSTDPtrMut) -> NSTDAnyMut {
373 ptr.raw
374}
375
376/// Returns a raw immutable pointer to the object pointed to by `ptr`.
377///
378/// # Parameters:
379///
380/// - `const NSTDPtrMut *ptr` - The higher level pointer.
381///
382/// # Returns
383///
384/// `NSTDAny raw` - A raw pointer to the object.
385///
386/// # Examples
387///
388/// ```
389/// use core::ptr::addr_of_mut;
390/// use nstd_sys::core::ptr::{nstd_core_ptr_mut_get_const, nstd_core_ptr_mut_new};
391///
392/// unsafe {
393/// const SIZE: usize = core::mem::size_of::<u32>();
394/// const ALIGN: usize = core::mem::align_of::<u32>();
395/// let mut x = 45u32;
396/// let ptr = nstd_core_ptr_mut_new(addr_of_mut!(x).cast(), SIZE, ALIGN).unwrap();
397/// assert!(*nstd_core_ptr_mut_get_const(&ptr).cast::<u32>() == x);
398/// }
399/// ```
400#[inline]
401#[nstdapi]
402pub const fn nstd_core_ptr_mut_get_const(ptr: &NSTDPtrMut) -> NSTDAny {
403 ptr.raw
404}
405
406/// Writes data from `obj` to `ptr`. The number of bytes written is determined by `ptr.size`.
407///
408/// # Note
409///
410/// It is up to the user of this function to ensure that `obj`'s memory buffer is at least
411/// `ptr.size` bytes wide to avoid writing garbage data to this pointer.
412///
413/// # Parameters:
414///
415/// - `NSTDPtrMut *ptr` - The pointer to write to.
416///
417/// - `NSTDAny obj` - A pointer to the object to write to `ptr`.
418///
419/// # Safety
420///
421/// This operation is highly unsafe because there is no way of knowing if `obj`'s data is valid.
422///
423/// # Examples
424///
425/// ```
426/// use core::ptr::{addr_of, addr_of_mut};
427/// use nstd_sys::core::ptr::{
428/// nstd_core_ptr_mut_get_const, nstd_core_ptr_mut_new, nstd_core_ptr_mut_write,
429/// };
430///
431/// unsafe {
432/// const SIZE: usize = core::mem::size_of::<i64>();
433/// const ALIGN: usize = core::mem::align_of::<i64>();
434/// let mut x = -69i64;
435/// let mut ptr = nstd_core_ptr_mut_new(addr_of_mut!(x).cast(), SIZE, ALIGN).unwrap();
436/// let y = 420i64;
437/// nstd_core_ptr_mut_write(&mut ptr, addr_of!(y).cast());
438/// assert!(x == y);
439/// }
440/// ```
441#[inline]
442#[nstdapi]
443pub unsafe fn nstd_core_ptr_mut_write(ptr: &mut NSTDPtrMut, obj: NSTDAny) {
444 nstd_core_mem_copy(ptr.raw.cast(), obj.cast(), ptr.size);
445}