nstd_sys/core/slice.rs
1//! A view into a sequence of values in memory.
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, NSTD_NULL,
8};
9use nstdapi::nstdapi;
10
11/// An immutable view into a sequence of values in memory.
12#[nstdapi]
13#[derive(Clone, Copy)]
14pub struct NSTDSlice {
15 /// A pointer to the first element in the slice.
16 ptr: NSTDAny,
17 /// The number of elements in the slice.
18 len: NSTDUInt,
19 /// The slice's stride.
20 stride: NSTDUInt,
21 /// The slice's align.
22 align: NSTDUInt,
23}
24impl NSTDSlice {
25 /// Creates a new [`NSTDSlice`] from a Rust slice.
26 #[inline]
27 #[allow(dead_code)]
28 pub(crate) const fn from_slice<T>(s: &[T]) -> Self {
29 Self {
30 ptr: s.as_ptr().cast(),
31 len: s.len(),
32 stride: core::mem::size_of::<T>(),
33 align: core::mem::align_of::<T>(),
34 }
35 }
36
37 /// Returns the number of bytes that this slice covers.
38 #[inline]
39 #[allow(clippy::arithmetic_side_effects)]
40 pub(crate) const fn byte_len(&self) -> usize {
41 self.len * self.stride
42 }
43
44 /// Creates a Rust slice from this `NSTDSlice`.
45 ///
46 /// Returns [`None`] if `size_of::<T>()` does not match the slice's stride.
47 ///
48 /// # Safety
49 ///
50 /// - The `NSTDSlice`'s data must remain valid and unmodified while the returned slice is in
51 /// use.
52 ///
53 /// - The slice's data must be properly aligned.
54 #[inline]
55 pub(crate) const unsafe fn as_slice<T>(&self) -> Option<&[T]> {
56 match self.stride == core::mem::size_of::<T>() {
57 true => Some(core::slice::from_raw_parts(self.ptr.cast(), self.len)),
58 false => None,
59 }
60 }
61}
62gen_optional!(NSTDOptionalSlice, NSTDSlice);
63
64/// Creates a new slice from raw data.
65///
66/// # Parameters:
67///
68/// - `NSTDAny ptr` - A pointer to the first element in the sequence.
69///
70/// - `NSTDUInt stride` - The number of bytes each element occupies.
71///
72/// - `NSTDUInt align` - The alignment of each element in the slice.
73///
74/// - `NSTDUInt len` - The number of elements in the sequence.
75///
76/// # Returns
77///
78/// `NSTDOptionalSlice slice` - The new slice on success, or an uninitialized "none" variant if
79/// `ptr` is null, `align` is not a power of two, `stride` is not a multiple of `align`, `ptr` is
80/// not a multiple of `align`, or the slice's length in bytes would exceed `NSTDInt`'s max value.
81#[nstdapi]
82pub fn nstd_core_slice_new(
83 ptr: NSTDAny,
84 stride: NSTDUInt,
85 align: NSTDUInt,
86 len: NSTDUInt,
87) -> NSTDOptionalSlice {
88 if let Some(size) = len.checked_mul(stride) {
89 #[allow(clippy::arithmetic_side_effects)]
90 if size <= NSTD_INT_MAX
91 && crate::core::mem::is_power_of_two(align)
92 && stride % align == 0
93 && !ptr.is_null()
94 && nstd_core_mem_is_aligned(ptr, align)
95 {
96 return NSTDOptional::Some(NSTDSlice {
97 ptr,
98 len,
99 stride,
100 align,
101 });
102 }
103 }
104 NSTDOptional::None
105}
106
107/// Creates a new slice from raw data without checking if `ptr` is null.
108///
109/// # Parameters:
110///
111/// - `NSTDAny ptr` - A pointer to the first element in the sequence.
112///
113/// - `NSTDUInt stride` - The number of bytes each element occupies.
114///
115/// - `NSTDUInt align` - The alignment of each element in the slice.
116///
117/// - `NSTDUInt len` - The number of elements in the sequence.
118///
119/// # Returns
120///
121/// `NSTDSlice slice` - The new slice.
122///
123/// # Safety
124///
125/// - `ptr` must be non-null.
126///
127/// - `align` must be a nonzero power of two.
128///
129/// - `stride` must be a multiple of `align`.
130///
131/// - `ptr` must be a multiple of `align`.
132///
133/// - The slice's total length in bytes will not exceed `NSTDInt`'s max value.
134#[inline]
135#[nstdapi]
136pub const unsafe fn nstd_core_slice_new_unchecked(
137 ptr: NSTDAny,
138 stride: NSTDUInt,
139 align: NSTDUInt,
140 len: NSTDUInt,
141) -> NSTDSlice {
142 NSTDSlice {
143 ptr,
144 len,
145 stride,
146 align,
147 }
148}
149
150/// Creates a new empty slice with a given `stride`.
151///
152/// # Parameters:
153///
154/// - `NSTDUInt stride` - The number of bytes each element occupies.
155///
156/// - `NSTDUInt align` - The alignment of each element in the slice.
157///
158/// # Returns
159///
160/// `NSTDSlice slice` - The new empty slice.
161///
162/// # Panics
163///
164/// This operation will panic if either `align` is not a power of two or `stride` is not a multiple
165/// of `align`.
166#[inline]
167#[nstdapi]
168#[allow(clippy::arithmetic_side_effects)]
169pub const fn nstd_core_slice_empty(stride: NSTDUInt, align: NSTDUInt) -> NSTDSlice {
170 assert!(crate::core::mem::is_power_of_two(align) && stride % align == 0);
171 NSTDSlice {
172 ptr: align as NSTDAny,
173 len: 0,
174 stride,
175 align,
176 }
177}
178
179/// Returns a raw pointer to the slice's memory.
180///
181/// # Parameters:
182///
183/// - `const NSTDSlice *slice` - The slice.
184///
185/// # Returns
186///
187/// `AnyConst ptr` - A raw pointer to the slice's memory.
188///
189/// # Example
190///
191/// ```
192/// use nstd_sys::core::slice::{nstd_core_slice_as_ptr, nstd_core_slice_new};
193///
194/// unsafe {
195/// let bytes = "Hello, world!".as_bytes();
196/// let bytes_ptr = bytes.as_ptr().cast();
197/// let slice = nstd_core_slice_new(bytes_ptr, 1, 1, bytes.len()).unwrap();
198/// assert!(nstd_core_slice_as_ptr(&slice) == bytes_ptr);
199/// }
200/// ```
201#[inline]
202#[nstdapi]
203pub const fn nstd_core_slice_as_ptr(slice: &NSTDSlice) -> NSTDAny {
204 slice.ptr
205}
206
207/// Returns the number of elements in an immutable slice.
208///
209/// # Parameters:
210///
211/// - `const NSTDSlice *slice` - The immutable slice.
212///
213/// # Returns
214///
215/// `NSTDUInt len` - The length of the slice.
216///
217/// # Example
218///
219/// ```
220/// use nstd_sys::core::slice::{nstd_core_slice_len, nstd_core_slice_new};
221///
222/// unsafe {
223/// let bytes = "Goodbye, world!".as_bytes();
224/// let len = bytes.len();
225/// let slice = nstd_core_slice_new(bytes.as_ptr().cast(), 1, 1, len).unwrap();
226/// assert!(nstd_core_slice_len(&slice) == len);
227/// }
228/// ```
229#[inline]
230#[nstdapi]
231pub const fn nstd_core_slice_len(slice: &NSTDSlice) -> NSTDUInt {
232 slice.len
233}
234
235/// Returns the amount of bytes each value in a slice occupies.
236///
237/// # Parameters:
238///
239/// - `const NSTDSlice *slice` - The slice.
240///
241/// # Returns
242///
243/// `NSTDUInt stride` - The size of each value in the slice.
244///
245/// # Example
246///
247/// ```
248/// use nstd_sys::core::slice::{nstd_core_slice_stride, nstd_core_slice_new};
249///
250/// unsafe {
251/// let bytes = "Hello, world!".as_bytes();
252/// let slice = nstd_core_slice_new(bytes.as_ptr().cast(), 1, 1, bytes.len()).unwrap();
253/// assert!(nstd_core_slice_stride(&slice) == 1);
254/// }
255/// ```
256#[inline]
257#[nstdapi]
258pub const fn nstd_core_slice_stride(slice: &NSTDSlice) -> NSTDUInt {
259 slice.stride
260}
261
262/// Returns the alignment of each value in a slice.
263///
264/// # Parameters:
265///
266/// - `const NSTDSlice *slice` - The slice.
267///
268/// # Returns
269///
270/// `NSTDUInt align` - The alignment of each value in the slice.
271///
272/// # Example
273///
274/// ```
275/// use nstd_sys::core::slice::{nstd_core_slice_align, nstd_core_slice_new};
276///
277/// unsafe {
278/// let bytes = "Hello, world!".as_bytes();
279/// let slice = nstd_core_slice_new(bytes.as_ptr().cast(), 1, 1, bytes.len()).unwrap();
280/// assert!(nstd_core_slice_align(&slice) == 1);
281/// }
282/// ```
283#[inline]
284#[nstdapi]
285pub const fn nstd_core_slice_align(slice: &NSTDSlice) -> NSTDUInt {
286 slice.align
287}
288
289/// Returns an immutable pointer to the element at index `pos` in `slice`.
290///
291/// # Parameters:
292///
293/// - `const NSTDSlice *slice` - The slice to read an element from.
294///
295/// - `NSTDUInt pos` - The position of the element to get, starting at 0.
296///
297/// # Returns
298///
299/// `NSTDAny element` - A pointer to the element at `pos` or `NSTD_NULL` if `pos` is out
300/// of the slice's boundaries.
301///
302/// # Example
303///
304/// ```
305/// use nstd_sys::core::slice::{nstd_core_slice_get, nstd_core_slice_new};
306///
307/// const STRIDE: usize = core::mem::size_of::<i32>();
308/// const ALIGN: usize = core::mem::align_of::<i32>();
309///
310/// unsafe {
311/// let numbers: [i32; 3] = [33, 103, 45];
312/// let slice =
313/// nstd_core_slice_new(numbers.as_ptr().cast(), STRIDE, ALIGN, numbers.len()).unwrap();
314///
315/// assert!(*nstd_core_slice_get(&slice, 0).cast::<i32>() == 33);
316/// assert!(*nstd_core_slice_get(&slice, 1).cast::<i32>() == 103);
317/// assert!(*nstd_core_slice_get(&slice, 2).cast::<i32>() == 45);
318/// assert!(nstd_core_slice_get(&slice, 3).is_null());
319/// }
320/// ```
321#[inline]
322#[nstdapi]
323pub const fn nstd_core_slice_get(slice: &NSTDSlice, mut pos: NSTDUInt) -> NSTDAny {
324 #[allow(clippy::arithmetic_side_effects)]
325 if pos < slice.len {
326 pos *= slice.stride;
327 // SAFETY: We've checked `pos`.
328 return unsafe { slice.ptr.add(pos) };
329 }
330 NSTD_NULL
331}
332
333/// Returns an immutable pointer to the first element in the slice.
334///
335/// # Parameters:
336///
337/// - `const NSTDSlice *slice` - The slice to get the first element of.
338///
339/// # Returns
340///
341/// `NSTDAny element` - A pointer to the first element in `slice` or `NSTD_NULL` if the
342/// slice is empty.
343///
344/// # Example
345///
346/// ```
347/// use nstd_sys::core::slice::{nstd_core_slice_first, nstd_core_slice_new};
348///
349/// const STRIDE: usize = core::mem::size_of::<u64>();
350/// const ALIGN: usize = core::mem::align_of::<u64>();
351///
352/// unsafe {
353/// let numbers: [u64; 3] = [707, 23043, 8008];
354/// let numbers_ptr = numbers.as_ptr().cast();
355/// let slice = nstd_core_slice_new(numbers_ptr, STRIDE, ALIGN, numbers.len()).unwrap();
356/// let empty = nstd_core_slice_new(numbers_ptr, STRIDE, ALIGN, 0).unwrap();
357///
358/// assert!(nstd_core_slice_first(&slice) == numbers_ptr);
359/// assert!(*nstd_core_slice_first(&slice).cast::<u64>() == 707);
360/// assert!(nstd_core_slice_first(&empty).is_null());
361/// }
362/// ```
363#[inline]
364#[nstdapi]
365pub const fn nstd_core_slice_first(slice: &NSTDSlice) -> NSTDAny {
366 match slice.len > 0 {
367 true => slice.ptr,
368 false => NSTD_NULL,
369 }
370}
371
372/// Returns an immutable pointer to the last element in the slice.
373///
374/// # Parameters:
375///
376/// - `const NSTDSlice *slice` - The slice to get the last element of.
377///
378/// # Returns
379///
380/// `NSTDAny element` - A pointer to the last element in `slice` or `NSTD_NULL` if the
381/// slice is empty.
382///
383/// # Example
384///
385/// ```
386/// use nstd_sys::core::slice::{nstd_core_slice_last, nstd_core_slice_new};
387///
388/// const STRIDE: usize = core::mem::size_of::<u64>();
389/// const ALIGN: usize = core::mem::align_of::<u64>();
390///
391/// unsafe {
392/// let numbers: [u64; 3] = [717, 421, 4317];
393/// let numbers_ptr = numbers.as_ptr().cast();
394/// let slice = nstd_core_slice_new(numbers_ptr, STRIDE, ALIGN, numbers.len()).unwrap();
395/// let empty = nstd_core_slice_new(numbers_ptr, STRIDE, ALIGN, 0).unwrap();
396///
397/// assert!(*nstd_core_slice_last(&slice).cast::<u64>() == 4317);
398/// assert!(nstd_core_slice_last(&empty).is_null());
399/// }
400/// ```
401#[inline]
402#[nstdapi]
403pub const fn nstd_core_slice_last(slice: &NSTDSlice) -> NSTDAny {
404 match slice.len > 0 {
405 #[allow(clippy::arithmetic_side_effects)]
406 true => nstd_core_slice_get(slice, slice.len - 1),
407 false => NSTD_NULL,
408 }
409}
410
411/// A view into a sequence of values in memory.
412#[nstdapi]
413pub struct NSTDSliceMut {
414 /// A pointer to the first element in the slice.
415 ptr: NSTDAnyMut,
416 /// The number of elements in the slice.
417 len: NSTDUInt,
418 /// The slice's stride.
419 stride: NSTDUInt,
420 /// The slice's align.
421 align: NSTDUInt,
422}
423impl NSTDSliceMut {
424 /// Creates a mutable Rust slice from this `NSTDSliceMut`.
425 ///
426 /// Returns [`None`] if `size_of::<T>()` does not match the slice's stride.
427 ///
428 /// # Safety
429 ///
430 /// - The `NSTDSliceMut`'s data must remain valid and unmodified while the returned slice is in
431 /// use.
432 ///
433 /// - The slice's data must be properly aligned.
434 #[inline]
435 #[allow(dead_code)]
436 pub(crate) unsafe fn as_slice_mut<T>(&mut self) -> Option<&mut [T]> {
437 match self.stride == core::mem::size_of::<T>() {
438 true => Some(core::slice::from_raw_parts_mut(self.ptr.cast(), self.len)),
439 false => None,
440 }
441 }
442}
443gen_optional!(NSTDOptionalSliceMut, NSTDSliceMut);
444
445/// Creates a new slice from raw data.
446///
447/// # Parameters:
448///
449/// - `NSTDAnyMut ptr` - A pointer to the first element in the sequence.
450///
451/// - `NSTDUInt stride` - The number of bytes each element occupies.
452///
453/// - `NSTDUInt align` - The alignment of each element in the slice.
454///
455/// - `NSTDUInt len` - The number of elements in the sequence.
456///
457/// # Returns
458///
459/// `NSTDOptionalSliceMut slice` - The new slice on success, or an uninitialized "none" variant if
460/// `ptr` is null, `align` is not a power of two, `stride` is not a multiple of `align`, `ptr` is
461/// not a multiple of `align`, or the slice's length in bytes would exceed `NSTDInt`'s max value.
462#[nstdapi]
463pub fn nstd_core_slice_mut_new(
464 ptr: NSTDAnyMut,
465 stride: NSTDUInt,
466 align: NSTDUInt,
467 len: NSTDUInt,
468) -> NSTDOptionalSliceMut {
469 if let Some(size) = len.checked_mul(stride) {
470 #[allow(clippy::arithmetic_side_effects)]
471 if size <= NSTD_INT_MAX
472 && crate::core::mem::is_power_of_two(align)
473 && stride % align == 0
474 && !ptr.is_null()
475 && nstd_core_mem_is_aligned(ptr, align)
476 {
477 return NSTDOptional::Some(NSTDSliceMut {
478 ptr,
479 len,
480 stride,
481 align,
482 });
483 }
484 }
485 NSTDOptional::None
486}
487
488/// Creates a new slice from raw data without checking if `ptr` is null.
489///
490/// # Parameters:
491///
492/// - `NSTDAnyMut ptr` - A pointer to the first element in the sequence.
493///
494/// - `NSTDUInt stride` - The number of bytes each element occupies.
495///
496/// - `NSTDUInt align` - The alignment of each element in the slice.
497///
498/// - `NSTDUInt len` - The number of elements in the sequence.
499///
500/// # Returns
501///
502/// `NSTDSliceMut slice` - The new slice.
503///
504/// # Safety
505///
506/// - `ptr` must be non-null.
507///
508/// - `align` must be a nonzero power of two.
509///
510/// - `stride` must be a multiple of `align`.
511///
512/// - `ptr` must be a multiple of `align`.
513///
514/// - The slice's total length in bytes will not exceed `NSTDInt`'s max value.
515#[inline]
516#[nstdapi]
517pub const unsafe fn nstd_core_slice_mut_new_unchecked(
518 ptr: NSTDAnyMut,
519 stride: NSTDUInt,
520 align: NSTDUInt,
521 len: NSTDUInt,
522) -> NSTDSliceMut {
523 NSTDSliceMut {
524 ptr,
525 len,
526 stride,
527 align,
528 }
529}
530
531/// Creates a new empty slice with a given `stride`.
532///
533/// # Parameters:
534///
535/// - `NSTDUInt stride` - The number of bytes each element occupies.
536///
537/// - `NSTDUInt align` - The alignment of each element in the slice.
538///
539/// # Returns
540///
541/// `NSTDSliceMut slice` - The new empty slice.
542///
543/// # Panics
544///
545/// This operation will panic if either `align` is not a power of two or `stride` is not a multiple
546/// of `align`.
547#[inline]
548#[nstdapi]
549#[allow(clippy::arithmetic_side_effects)]
550pub const fn nstd_core_slice_mut_empty(stride: NSTDUInt, align: NSTDUInt) -> NSTDSliceMut {
551 assert!(crate::core::mem::is_power_of_two(align) && stride % align == 0);
552 NSTDSliceMut {
553 ptr: align as NSTDAnyMut,
554 len: 0,
555 stride,
556 align,
557 }
558}
559
560/// Creates an immutable version of a mutable slice.
561///
562/// # Parameters:
563///
564/// - `const NSTDSliceMut *slice` - The mutable slice.
565///
566/// # Returns
567///
568/// `NSTDSlice slice_const` - The immutable copy of `slice`.
569#[inline]
570#[nstdapi]
571pub const fn nstd_core_slice_mut_as_const(slice: &NSTDSliceMut) -> NSTDSlice {
572 let ptr = nstd_core_slice_mut_as_ptr_const(slice);
573 let stride = nstd_core_slice_mut_stride(slice);
574 // SAFETY: `ptr` is never null.
575 unsafe { nstd_core_slice_new_unchecked(ptr, stride, slice.align, slice.len) }
576}
577
578/// Returns a raw pointer to the slice's memory.
579///
580/// # Parameters:
581///
582/// - `NSTDSliceMut *slice` - The slice.
583///
584/// # Returns
585///
586/// `NSTDAnyMut ptr` - A raw pointer to the slice's memory.
587///
588/// # Example
589///
590/// ```
591/// use nstd_sys::core::slice::{
592/// nstd_core_slice_mut_as_ptr, nstd_core_slice_mut_get_const, nstd_core_slice_mut_new,
593/// };
594///
595/// const STRIDE: usize = core::mem::size_of::<u16>();
596/// const ALIGN: usize = core::mem::align_of::<u16>();
597///
598/// unsafe {
599/// let mut buf: [u16; 3] = [3, 5, 7];
600/// let ptr = buf.as_mut_ptr().cast();
601/// let mut slice = nstd_core_slice_mut_new(ptr, STRIDE, ALIGN, buf.len()).unwrap();
602///
603/// *nstd_core_slice_mut_as_ptr(&mut slice).cast::<u16>() = 1;
604/// assert!(*nstd_core_slice_mut_get_const(&slice, 0).cast::<u16>() == 1);
605/// }
606/// ```
607#[inline]
608#[nstdapi]
609pub fn nstd_core_slice_mut_as_ptr(slice: &mut NSTDSliceMut) -> NSTDAnyMut {
610 slice.ptr
611}
612
613/// Returns an immutable raw pointer to the slice's memory.
614///
615/// # Parameters:
616///
617/// - `const NSTDSliceMut *slice` - The slice.
618///
619/// # Returns
620///
621/// `NSTDAny ptr` - A raw pointer to the slice's memory.
622///
623/// # Example
624///
625/// ```
626/// use nstd_sys::core::slice::{nstd_core_slice_mut_as_ptr_const, nstd_core_slice_mut_new};
627///
628/// unsafe {
629/// let mut m33 = String::from("33marrow");
630/// let raw_ptr = m33.as_mut_ptr().cast();
631/// let slice = nstd_core_slice_mut_new(raw_ptr, 1, 1, m33.len()).unwrap();
632/// assert!(nstd_core_slice_mut_as_ptr_const(&slice) == raw_ptr);
633/// }
634/// ```
635#[inline]
636#[nstdapi]
637pub const fn nstd_core_slice_mut_as_ptr_const(slice: &NSTDSliceMut) -> NSTDAny {
638 slice.ptr
639}
640
641/// Returns the number of elements in a slice.
642///
643/// # Parameters:
644///
645/// - `const NSTDSliceMut *slice` - The slice.
646///
647/// # Returns
648///
649/// `NSTDUInt len` - The length of the slice.
650///
651/// # Example
652///
653/// ```
654/// use nstd_sys::core::slice::{nstd_core_slice_mut_len, nstd_core_slice_mut_new};
655///
656/// unsafe {
657/// let mut bye = String::from("Goodbye, cruel world!");
658/// let len = bye.len();
659/// let slice = nstd_core_slice_mut_new(bye.as_mut_ptr().cast(), 1, 1, len).unwrap();
660/// assert!(nstd_core_slice_mut_len(&slice) == len);
661/// }
662/// ```
663#[inline]
664#[nstdapi]
665pub const fn nstd_core_slice_mut_len(slice: &NSTDSliceMut) -> NSTDUInt {
666 slice.len
667}
668
669/// Returns the amount of bytes each value in a slice occupies.
670///
671/// # Parameters:
672///
673/// - `const NSTDSliceMut *slice` - The slice.
674///
675/// # Returns
676///
677/// `NSTDUInt stride` - The size of each value in the slice.
678///
679/// # Example
680///
681/// ```
682/// use nstd_sys::core::slice::{nstd_core_slice_mut_stride, nstd_core_slice_mut_new};
683///
684/// unsafe {
685/// let mut hw = String::from("Hello, world!");
686/// let slice = nstd_core_slice_mut_new(hw.as_mut_ptr().cast(), 1, 1, hw.len()).unwrap();
687/// assert!(nstd_core_slice_mut_stride(&slice) == 1);
688/// }
689/// ```
690#[inline]
691#[nstdapi]
692pub const fn nstd_core_slice_mut_stride(slice: &NSTDSliceMut) -> NSTDUInt {
693 slice.stride
694}
695
696/// Returns the alignment of each value in a slice.
697///
698/// # Parameters:
699///
700/// - `const NSTDSliceMut *slice` - The slice.
701///
702/// # Returns
703///
704/// `NSTDUInt align` - The alignment of each value in the slice.
705///
706/// # Example
707///
708/// ```
709/// use nstd_sys::core::slice::{nstd_core_slice_mut_align, nstd_core_slice_mut_new};
710///
711/// unsafe {
712/// let mut bytes = b"Hello, world!".to_vec();
713/// let slice = nstd_core_slice_mut_new(bytes.as_mut_ptr().cast(), 1, 1, bytes.len()).unwrap();
714/// assert!(nstd_core_slice_mut_align(&slice) == 1);
715/// }
716/// ```
717#[inline]
718#[nstdapi]
719pub const fn nstd_core_slice_mut_align(slice: &NSTDSliceMut) -> NSTDUInt {
720 slice.align
721}
722
723/// Returns a pointer to the element at index `pos` in `slice`.
724///
725/// # Parameters:
726///
727/// - `NSTDSliceMut *slice` - The slice to read an element from.
728///
729/// - `NSTDUInt pos` - The position of the element to get, starting at 0.
730///
731/// # Returns
732///
733/// `NSTDAnyMut element` - A pointer to the element at `pos` or `NSTD_NULL` if `pos` is out of
734/// the slice's boundaries.
735///
736/// # Example
737///
738/// ```
739/// use nstd_sys::core::slice::{nstd_core_slice_mut_get, nstd_core_slice_mut_new};
740///
741/// const STRIDE: usize = core::mem::size_of::<i32>();
742/// const ALIGN: usize = core::mem::align_of::<i32>();
743///
744/// unsafe {
745/// let mut numbers = [0i32; 3];
746/// let ptr = numbers.as_mut_ptr().cast();
747/// let mut slice = nstd_core_slice_mut_new(ptr, STRIDE, ALIGN, numbers.len()).unwrap();
748///
749/// *nstd_core_slice_mut_get(&mut slice, 0).cast::<i32>() = 33;
750/// *nstd_core_slice_mut_get(&mut slice, 1).cast::<i32>() = 103;
751/// *nstd_core_slice_mut_get(&mut slice, 2).cast::<i32>() = 45;
752/// assert!(numbers == [33, 103, 45]);
753/// }
754/// ```
755#[inline]
756#[nstdapi]
757pub fn nstd_core_slice_mut_get(slice: &mut NSTDSliceMut, pos: NSTDUInt) -> NSTDAnyMut {
758 nstd_core_slice_mut_get_const(slice, pos).cast_mut()
759}
760
761/// Returns an immutable pointer to the element at index `pos` in `slice`.
762///
763/// # Parameters:
764///
765/// - `const NSTDSliceMut *slice` - The slice to read an element from.
766///
767/// - `NSTDUInt pos` - The position of the element to get, starting at 0.
768///
769/// # Returns
770///
771/// `NSTDAny element` - A pointer to the element at `pos` or `NSTD_NULL` if `pos` is out
772/// of the slice's boundaries.
773///
774/// # Example
775///
776/// ```
777/// use nstd_sys::core::slice::{nstd_core_slice_mut_get_const, nstd_core_slice_mut_new};
778///
779/// const STRIDE: usize = core::mem::size_of::<i32>();
780/// const ALIGN: usize = core::mem::align_of::<i32>();
781///
782/// unsafe {
783/// let mut numbers: [i32; 3] = [33, 103, 45];
784/// let ptr = numbers.as_mut_ptr().cast();
785/// let slice = nstd_core_slice_mut_new(ptr, STRIDE, ALIGN, numbers.len()).unwrap();
786///
787/// assert!(*nstd_core_slice_mut_get_const(&slice, 0).cast::<i32>() == 33);
788/// assert!(*nstd_core_slice_mut_get_const(&slice, 1).cast::<i32>() == 103);
789/// assert!(*nstd_core_slice_mut_get_const(&slice, 2).cast::<i32>() == 45);
790/// assert!(nstd_core_slice_mut_get_const(&slice, 3).is_null());
791/// }
792/// ```
793#[inline]
794#[nstdapi]
795pub const fn nstd_core_slice_mut_get_const(slice: &NSTDSliceMut, mut pos: NSTDUInt) -> NSTDAny {
796 #[allow(clippy::arithmetic_side_effects)]
797 if pos < slice.len {
798 pos *= slice.stride;
799 // SAFETY: We've checked `pos`.
800 return unsafe { slice.ptr.add(pos) };
801 }
802 NSTD_NULL
803}
804
805/// Returns a pointer to the first element in the slice.
806///
807/// # Parameters:
808///
809/// - `NSTDSliceMut *slice` - The slice to get the first element of.
810///
811/// # Returns
812///
813/// `NSTDAnyMut element` - A pointer to the first element in `slice` or `NSTD_NULL` if the slice
814/// is empty.
815///
816/// # Example
817///
818/// ```
819/// use nstd_sys::core::slice::{nstd_core_slice_mut_first, nstd_core_slice_mut_new};
820///
821/// const STRIDE: usize = core::mem::size_of::<u64>();
822/// const ALIGN: usize = core::mem::align_of::<u64>();
823///
824/// let mut numbers: [u64; 3] = [707, 23043, 8008];
825/// let ptr = numbers.as_mut_ptr().cast();
826/// let mut slice = unsafe { nstd_core_slice_mut_new(ptr, STRIDE, ALIGN, numbers.len()).unwrap() };
827///
828/// unsafe { *nstd_core_slice_mut_first(&mut slice).cast::<u64>() = 101 };
829/// assert!(numbers[0] == 101);
830/// ```
831#[inline]
832#[nstdapi]
833pub fn nstd_core_slice_mut_first(slice: &mut NSTDSliceMut) -> NSTDAnyMut {
834 nstd_core_slice_mut_first_const(slice).cast_mut()
835}
836
837/// Returns an immutable pointer to the first element in the slice.
838///
839/// # Parameters:
840///
841/// - `const NSTDSliceMut *slice` - The slice to get the first element of.
842///
843/// # Returns
844///
845/// `NSTDAny element` - A pointer to the first element in `slice` or `NSTD_NULL` if the
846/// slice is empty.
847///
848/// # Example
849///
850/// ```
851/// use nstd_sys::core::slice::{nstd_core_slice_mut_first_const, nstd_core_slice_mut_new};
852///
853/// const STRIDE: usize = core::mem::size_of::<u64>();
854/// const ALIGN: usize = core::mem::align_of::<u64>();
855///
856/// unsafe {
857/// let mut numbers: [u64; 3] = [707, 23043, 8008];
858/// let numbers_ptr = numbers.as_mut_ptr().cast();
859/// let slice = nstd_core_slice_mut_new(numbers_ptr, STRIDE, ALIGN, numbers.len()).unwrap();
860/// let empty = nstd_core_slice_mut_new(numbers_ptr, STRIDE, ALIGN, 0).unwrap();
861///
862/// assert!(nstd_core_slice_mut_first_const(&slice) == numbers_ptr);
863/// assert!(*nstd_core_slice_mut_first_const(&slice).cast::<u64>() == 707);
864/// assert!(nstd_core_slice_mut_first_const(&empty).is_null());
865/// }
866/// ```
867#[inline]
868#[nstdapi]
869pub const fn nstd_core_slice_mut_first_const(slice: &NSTDSliceMut) -> NSTDAny {
870 match slice.len > 0 {
871 true => nstd_core_slice_mut_as_ptr_const(slice),
872 false => NSTD_NULL,
873 }
874}
875
876/// Returns a pointer to the last element in the slice.
877///
878/// # Parameters:
879///
880/// - `NSTDSliceMut *slice` - The slice to get the last element of.
881///
882/// # Returns
883///
884/// `NSTDAnyMut element` - A pointer to the last element in `slice` or `NSTD_NULL` if the slice
885/// is empty.
886///
887/// # Example
888///
889/// ```
890/// use nstd_sys::core::slice::{nstd_core_slice_mut_last, nstd_core_slice_mut_new};
891///
892/// const STRIDE: usize = core::mem::size_of::<u64>();
893/// const ALIGN: usize = core::mem::align_of::<u64>();
894///
895/// unsafe {
896/// let mut numbers: [u64; 3] = [717, 421, 4317];
897/// let ptr = numbers.as_mut_ptr().cast();
898/// let mut slice = nstd_core_slice_mut_new(ptr, STRIDE, ALIGN, numbers.len()).unwrap();
899///
900/// *nstd_core_slice_mut_last(&mut slice).cast::<u64>() = 1738;
901/// assert!(numbers[2] == 1738);
902/// }
903/// ```
904#[inline]
905#[nstdapi]
906pub fn nstd_core_slice_mut_last(slice: &mut NSTDSliceMut) -> NSTDAnyMut {
907 nstd_core_slice_mut_last_const(slice).cast_mut()
908}
909
910/// Returns an immutable pointer to the last element in the slice.
911///
912/// # Parameters:
913///
914/// - `const NSTDSliceMut *slice` - The slice to get the last element of.
915///
916/// # Returns
917///
918/// `NSTDAny element` - A pointer to the last element in `slice` or `NSTD_NULL` if the
919/// slice is empty.
920///
921/// # Example
922///
923/// ```
924/// use nstd_sys::core::slice::{nstd_core_slice_mut_last_const, nstd_core_slice_mut_new};
925///
926/// const STRIDE: usize = core::mem::size_of::<u64>();
927/// const ALIGN: usize = core::mem::align_of::<u64>();
928///
929/// unsafe {
930/// let mut numbers: [u64; 3] = [717, 421, 4317];
931/// let numbers_ptr = numbers.as_mut_ptr().cast();
932/// let slice = nstd_core_slice_mut_new(numbers_ptr, STRIDE, ALIGN, numbers.len()).unwrap();
933/// let empty = nstd_core_slice_mut_new(numbers_ptr, STRIDE, ALIGN, 0).unwrap();
934///
935/// assert!(*nstd_core_slice_mut_last_const(&slice).cast::<u64>() == 4317);
936/// assert!(nstd_core_slice_mut_last_const(&empty).is_null());
937/// }
938/// ```
939#[inline]
940#[nstdapi]
941pub const fn nstd_core_slice_mut_last_const(slice: &NSTDSliceMut) -> NSTDAny {
942 match slice.len > 0 {
943 #[allow(clippy::arithmetic_side_effects)]
944 true => nstd_core_slice_mut_get_const(slice, slice.len - 1),
945 false => NSTD_NULL,
946 }
947}
948
949/// Copies data into `dest` from `src`. The number of bytes copied is determined by `src`.
950///
951/// # Parameters:
952///
953/// - `NSTDSliceMut *dest` - The slice to copy data to.
954///
955/// - `const NSTDSlice *src` - The slice to copy data from.
956///
957/// # Panics
958///
959/// This operation will panic in the following situations:
960///
961/// - The two buffer's lengths do not match.
962///
963/// - The two buffer's strides do not match.
964///
965/// # Safety
966///
967/// This function can cause undefined behavior if either `dest` or `src`'s data is invalid.
968///
969/// # Example
970///
971/// ```
972/// use nstd_sys::core::slice::{
973/// nstd_core_slice_mut_copy, nstd_core_slice_mut_new, nstd_core_slice_new,
974/// };
975///
976/// const STRIDE: usize = core::mem::size_of::<u32>();
977/// const ALIGN: usize = core::mem::align_of::<u32>();
978///
979/// let mut dest_arr = [0u32; 5];
980/// let src_arr: [u32; 5] = [7, 43, 32, 90, 15];
981///
982/// unsafe {
983/// let ptr = dest_arr.as_mut_ptr().cast();
984/// let mut dest = nstd_core_slice_mut_new(ptr, STRIDE, ALIGN, dest_arr.len()).unwrap();
985/// let src =
986/// nstd_core_slice_new(src_arr.as_ptr().cast(), STRIDE, ALIGN, src_arr.len()).unwrap();
987///
988/// nstd_core_slice_mut_copy(&mut dest, &src);
989/// assert!(dest_arr == src_arr);
990/// }
991/// ```
992#[nstdapi]
993pub unsafe fn nstd_core_slice_mut_copy(dest: &mut NSTDSliceMut, src: &NSTDSlice) {
994 assert!(dest.len == src.len && dest.stride == src.stride);
995 let len = src.byte_len();
996 let dest = nstd_core_slice_mut_as_ptr(dest).cast();
997 let src = nstd_core_slice_as_ptr(src).cast();
998 nstd_core_mem_copy(dest, src, len);
999}