nstd_sys/core/
str.rs

1//! An unowned view into a UTF-8 encoded byte string.
2use crate::{
3    core::{
4        cstr::{
5            nstd_core_cstr_as_ptr, nstd_core_cstr_len, nstd_core_cstr_mut_as_ptr,
6            nstd_core_cstr_mut_len, nstd_core_cstr_new_unchecked,
7            raw::{nstd_core_cstr_raw_len, nstd_core_cstr_raw_len_with_null},
8            NSTDCStr, NSTDCStrMut,
9        },
10        def::NSTDByte,
11        optional::{
12            gen_optional, NSTDOptional, NSTDOptionalFloat32, NSTDOptionalFloat64, NSTDOptionalInt,
13            NSTDOptionalInt16, NSTDOptionalInt32, NSTDOptionalInt64, NSTDOptionalInt8,
14            NSTDOptionalUInt, NSTDOptionalUInt16, NSTDOptionalUInt32, NSTDOptionalUInt64,
15            NSTDOptionalUInt8,
16        },
17        range::NSTDURange,
18        slice::{
19            nstd_core_slice_as_ptr, nstd_core_slice_len, nstd_core_slice_mut_as_ptr,
20            nstd_core_slice_mut_len, nstd_core_slice_mut_new_unchecked, nstd_core_slice_mut_stride,
21            nstd_core_slice_new_unchecked, nstd_core_slice_stride, NSTDSlice, NSTDSliceMut,
22        },
23        unichar::NSTDOptionalUnichar,
24    },
25    NSTDChar, NSTDUInt, NSTD_INT_MAX,
26};
27use nstdapi::nstdapi;
28
29/// Generates the `nstd_core_str_*_to_[i|u|f]*` functions.
30macro_rules! gen_to_primitive {
31    (
32        $(#[$meta:meta])*
33        $name: ident, $StrT: ty, $T: ty, $RetT: ty
34    ) => {
35        #[doc = concat!("Attempts to parse a string slice as an `", stringify!($T), "`.")]
36        ///
37        /// # Parameters:
38        ///
39        /// - `const NSTDStr *str` - The string slice.
40        ///
41        /// # Returns
42        ///
43        #[doc = concat!("`", stringify!($RetT), " v` - The parsed value, or none on error.")]
44        ///
45        /// # Safety
46        ///
47        /// This operation can cause undefined behavior in the event that `str`'s data is invalid.
48        ///
49        $(#[$meta])*
50        #[inline]
51        #[nstdapi]
52        pub unsafe fn $name(str: &$StrT) -> $RetT {
53            match str.as_str().parse() {
54                Ok(v) => NSTDOptional::Some(v),
55                _ => NSTDOptional::None,
56            }
57        }
58    };
59}
60
61/// An immutable unowned view into a UTF-8 encoded byte string.
62#[nstdapi]
63#[derive(Clone, Copy)]
64pub struct NSTDStr {
65    /// A raw pointer to the string's data.
66    ptr: *const NSTDByte,
67    /// The number of bytes in the string.
68    len: NSTDUInt,
69}
70impl NSTDStr {
71    /// Creates a new [`NSTDStr`] from a Rust [&str].
72    #[inline]
73    #[allow(dead_code)]
74    pub(crate) const fn from_str(str: &str) -> Self {
75        Self {
76            ptr: str.as_ptr(),
77            len: str.len(),
78        }
79    }
80
81    /// Creates a Rust string slice from this [`NSTDStr`].
82    ///
83    /// # Safety
84    ///
85    /// This string slice's data must remain valid UTF-8 and left unmodified while the returned
86    /// string slice is in use.
87    #[inline]
88    pub(crate) const unsafe fn as_str(&self) -> &str {
89        let bytes = core::slice::from_raw_parts(self.ptr, self.len);
90        core::str::from_utf8_unchecked(bytes)
91    }
92}
93gen_optional!(NSTDOptionalStr, NSTDStr);
94
95/// Creates a new instance of an `NSTDStr` from a C string slice.
96///
97/// # Parameters:
98///
99/// - `const NSTDCStr *cstr` - The C string slice to wrap.
100///
101/// # Returns
102///
103/// `NSTDOptionalStr str` - The new `NSTDStr` instance on success, or a "none" variant if the
104/// result is not valid UTF-8.
105///
106/// # Safety
107///
108/// `cstr`'s data must be valid for reads of at least `cstr.len` consecutive bytes.
109///
110/// # Example
111///
112/// ```
113/// use nstd_sys::core::{
114///     cstr::nstd_core_cstr_from_raw,
115///     str::{nstd_core_str_byte_len, nstd_core_str_from_cstr},
116/// };
117///
118/// let s_str = "Hello, world!\0";
119/// unsafe {
120///     let cstr = nstd_core_cstr_from_raw(s_str.as_ptr().cast());
121///     let str = nstd_core_str_from_cstr(&cstr).unwrap();
122///     assert!(nstd_core_str_byte_len(&str) == 13);
123/// }
124/// ```
125#[nstdapi]
126pub const unsafe fn nstd_core_str_from_cstr(cstr: &NSTDCStr) -> NSTDOptionalStr {
127    match core::str::from_utf8(cstr.as_bytes()).is_ok() {
128        true => {
129            let ptr = nstd_core_cstr_as_ptr(cstr).cast();
130            let len = nstd_core_cstr_len(cstr);
131            NSTDOptional::Some(NSTDStr { ptr, len })
132        }
133        false => NSTDOptional::None,
134    }
135}
136
137/// Creates a new instance of an `NSTDStr` from a C string slice.
138///
139/// # Parameters:
140///
141/// - `const NSTDCStr *cstr` - The C string slice to wrap.
142///
143/// # Returns
144///
145/// `NSTDStr str` - The new `NSTDStr` instance.
146///
147/// # Safety
148///
149/// This function does not check to ensure that `cstr` is valid UTF-8. `cstr`'s data must remain
150/// valid while the returned string slice is in use.
151///
152/// # Example
153///
154/// ```
155/// use nstd_sys::core::{
156///     cstr::nstd_core_cstr_from_raw,
157///     str::{nstd_core_str_byte_len, nstd_core_str_from_cstr_unchecked},
158/// };
159///
160/// let s_str = "Goodbye, world!\0";
161/// unsafe {
162///     let cstr = nstd_core_cstr_from_raw(s_str.as_ptr().cast());
163///     let str = nstd_core_str_from_cstr_unchecked(&cstr);
164///     assert!(nstd_core_str_byte_len(&str) == 15);
165/// }
166/// ```
167#[inline]
168#[nstdapi]
169pub const unsafe fn nstd_core_str_from_cstr_unchecked(cstr: &NSTDCStr) -> NSTDStr {
170    let ptr = nstd_core_cstr_as_ptr(cstr).cast();
171    let len = nstd_core_cstr_len(cstr);
172    NSTDStr { ptr, len }
173}
174
175/// Creates a new `NSTDStr` from a raw C string.
176///
177/// # Parameters:
178///
179/// - `const NSTDChar *cstr` - The raw C string to wrap.
180///
181/// # Returns
182///
183/// `NSTDOptionalStr str` - The new string slice on success or an uninitialized "none" variant if
184/// `cstr` is null, `cstr`'s length exceeds `NSTDInt`'s max value, or `cstr` is not valid UTF-8.
185///
186/// # Safety
187///
188/// `cstr` must point to a character array that is valid for reads up until and including it's
189/// null-terminating byte.
190///
191/// # Example
192///
193/// ```
194/// use nstd_sys::core::str::{nstd_core_str_byte_len, nstd_core_str_from_raw_cstr};
195///
196/// let s_str = "Where I live is where I bleed.\0";
197/// unsafe {
198///     let str = nstd_core_str_from_raw_cstr(s_str.as_ptr().cast()).unwrap();
199///     assert!(nstd_core_str_byte_len(&str) == 30);
200/// }
201/// ```
202#[nstdapi]
203pub unsafe fn nstd_core_str_from_raw_cstr(cstr: *const NSTDChar) -> NSTDOptionalStr {
204    if !cstr.is_null() {
205        let len = nstd_core_cstr_raw_len(cstr);
206        if len <= NSTD_INT_MAX {
207            let ptr = cstr.cast();
208            let bytes = core::slice::from_raw_parts(ptr, len);
209            if core::str::from_utf8(bytes).is_ok() {
210                return NSTDOptional::Some(NSTDStr { ptr, len });
211            }
212        }
213    }
214    NSTDOptional::None
215}
216
217/// Creates a new `NSTDStr` from a raw C string, including the null byte.
218///
219/// # Parameters:
220///
221/// - `const NSTDChar *cstr` - The raw C string to wrap.
222///
223/// # Returns
224///
225/// `NSTDOptionalStr str` - The new string slice on success or an uninitialized "none" variant if
226/// `cstr` is null, `cstr`'s length exceeds `NSTDInt`'s max value, or `cstr` is not valid UTF-8.
227///
228/// # Safety
229///
230/// `cstr` must point to a character array that is valid for reads up until and including it's
231/// null-terminating byte.
232///
233/// # Example
234///
235/// ```
236/// use nstd_sys::core::str::{nstd_core_str_byte_len, nstd_core_str_from_raw_cstr_with_null};
237///
238/// let s_str = "{Hello, world!}}}%\0";
239/// unsafe {
240///     let str = nstd_core_str_from_raw_cstr_with_null(s_str.as_ptr().cast()).unwrap();
241///     assert!(nstd_core_str_byte_len(&str) == 19);
242/// }
243/// ```
244#[nstdapi]
245pub unsafe fn nstd_core_str_from_raw_cstr_with_null(cstr: *const NSTDChar) -> NSTDOptionalStr {
246    if !cstr.is_null() {
247        let len = nstd_core_cstr_raw_len_with_null(cstr);
248        if len <= NSTD_INT_MAX {
249            let ptr = cstr.cast();
250            let bytes = core::slice::from_raw_parts(ptr, len);
251            if core::str::from_utf8(bytes).is_ok() {
252                return NSTDOptional::Some(NSTDStr { ptr, len });
253            }
254        }
255    }
256    NSTDOptional::None
257}
258
259/// Creates a string slice from raw bytes.
260///
261/// # Parameters:
262///
263/// - `const NSTDSlice *bytes` - The UTF-8 encoded byte slice.
264///
265/// # Returns
266///
267/// `NSTDOptionalStr str` - The new string slice on success, or a "none" variant if the
268/// result is not valid UTF-8.
269///
270/// # Safety
271///
272/// - `bytes` must remain valid while the returned string slice is in use.
273///
274/// - `bytes`'s data must be valid for reads of at least `bytes.len` consecutive bytes.
275///
276/// # Example
277///
278/// ```
279/// use nstd_sys::core::{
280///     slice::nstd_core_slice_new,
281///     str::{nstd_core_str_byte_len, nstd_core_str_from_bytes},
282/// };
283///
284/// let s_str = "Hello, world!\0";
285/// unsafe {
286///     let bytes = nstd_core_slice_new(s_str.as_ptr().cast(), 1, 1, s_str.len()).unwrap();
287///     let str = nstd_core_str_from_bytes(&bytes).unwrap();
288///     assert!(nstd_core_str_byte_len(&str) == 14);
289/// }
290/// ```
291#[nstdapi]
292pub const unsafe fn nstd_core_str_from_bytes(bytes: &NSTDSlice) -> NSTDOptionalStr {
293    if let Some(bytes) = bytes.as_slice() {
294        if core::str::from_utf8(bytes).is_ok() {
295            return NSTDOptional::Some(NSTDStr {
296                ptr: bytes.as_ptr(),
297                len: bytes.len(),
298            });
299        }
300    }
301    NSTDOptional::None
302}
303
304/// Creates a string slice from raw bytes, without checking for UTF-8.
305///
306/// # Parameters:
307///
308/// - `const NSTDSlice *bytes` - The UTF-8 encoded byte slice.
309///
310/// # Returns
311///
312/// `NSTDStr str` - The new string slice.
313///
314/// # Panics
315///
316/// This operation will panic if `bytes`'s stride is not 1.
317///
318/// # Safety
319///
320/// - This function does not check to ensure that `bytes` are valid UTF-8.
321///
322/// - `bytes` must remain valid while the returned string slice is in use.
323///
324/// - `bytes`'s data must be valid for reads of at least `bytes.len` consecutive bytes.
325///
326/// # Example
327///
328/// ```
329/// use nstd_sys::core::{
330///     slice::nstd_core_slice_new,
331///     str::{nstd_core_str_byte_len, nstd_core_str_from_bytes_unchecked},
332/// };
333///
334/// let s_str = "Goodbye, world!\0";
335/// unsafe {
336///     let bytes = nstd_core_slice_new(s_str.as_ptr().cast(), 1, 1, s_str.len()).unwrap();
337///     let str = nstd_core_str_from_bytes_unchecked(&bytes);
338///     assert!(nstd_core_str_byte_len(&str) == 16);
339/// }
340/// ```
341#[inline]
342#[nstdapi]
343pub const unsafe fn nstd_core_str_from_bytes_unchecked(bytes: &NSTDSlice) -> NSTDStr {
344    assert!(nstd_core_slice_stride(bytes) == 1);
345    let ptr = nstd_core_slice_as_ptr(bytes).cast();
346    let len = nstd_core_slice_len(bytes);
347    NSTDStr { ptr, len }
348}
349
350/// Returns a C string slice variant of this UTF-8 encoded string slice.
351///
352/// # Parameters:
353///
354/// - `const NSTDStr *str` - The UTF-8 encoded string slice.
355///
356/// # Returns
357///
358/// `NSTDCStr cstr` - The new C string slice.
359#[inline]
360#[nstdapi]
361pub const fn nstd_core_str_as_cstr(str: &NSTDStr) -> NSTDCStr {
362    // SAFETY: `str.ptr` is never null, string slices are never longer than `NSTDInt`'s max value.
363    unsafe { nstd_core_cstr_new_unchecked(str.ptr.cast(), str.len) }
364}
365
366/// Returns an immutable byte slice over `str`'s data.
367///
368/// # Parameters:
369///
370/// - `const NSTDStr *str` - The string slice.
371///
372/// # Returns
373///
374/// `NSTDSlice bytes` - An immutable byte slice over `str`'s data.
375///
376/// # Example
377///
378/// ```
379/// use nstd_sys::core::{
380///     slice::nstd_core_slice_len,
381///     str::{nstd_core_str_as_bytes, nstd_core_str_byte_len, nstd_core_str_from_raw_cstr},
382/// };
383///
384/// let s_str = "We won't be alone 🎶\0";
385/// unsafe {
386///     let str = nstd_core_str_from_raw_cstr(s_str.as_ptr().cast()).unwrap();
387///     let bytes = nstd_core_str_as_bytes(&str);
388///     assert!(nstd_core_str_byte_len(&str) == nstd_core_slice_len(&bytes));
389/// }
390/// ```
391#[inline]
392#[nstdapi]
393pub const fn nstd_core_str_as_bytes(str: &NSTDStr) -> NSTDSlice {
394    // SAFETY: `str.ptr` is never null, string slice lengths are never greater than `NSTDInt`'s max
395    // value.
396    unsafe { nstd_core_slice_new_unchecked(str.ptr.cast(), 1, 1, str.len) }
397}
398
399/// Returns a raw pointer to a string slice's memory.
400///
401/// # Parameters:
402///
403/// - `const NSTDStr *str` - The string slice.
404///
405/// # Returns
406///
407/// `const NSTDByte *ptr` - A raw pointer to a string slice's memory.
408#[inline]
409#[nstdapi]
410pub const fn nstd_core_str_as_ptr(str: &NSTDStr) -> *const NSTDByte {
411    str.ptr
412}
413
414/// Returns the number of Unicode characters in a string slice.
415///
416/// # Parameters:
417///
418/// - `const NSTDStr *str` - The string slice.
419///
420/// # Returns
421///
422/// `NSTDUInt len` - The length of the string slice.
423///
424/// # Safety
425///
426/// This operation can cause undefined behavior in the event that `str`'s data is invalid.
427///
428/// # Example
429///
430/// ```
431/// use nstd_sys::core::str::{nstd_core_str_len, nstd_core_str_from_raw_cstr};
432///
433/// let s_str = "Hello, 🌎!\0";
434/// unsafe {
435///     let str = nstd_core_str_from_raw_cstr(s_str.as_ptr().cast()).unwrap();
436///     assert!(nstd_core_str_len(&str) == 9);
437/// }
438/// ```
439#[inline]
440#[nstdapi]
441pub unsafe fn nstd_core_str_len(str: &NSTDStr) -> NSTDUInt {
442    str.as_str().chars().count()
443}
444
445/// Returns the number of bytes a string slice contains.
446///
447/// # Parameters:
448///
449/// - `const NSTDStr *str` - The string slice.
450///
451/// # Returns
452///
453/// `NSTDUInt byte_len` - The number of bytes in the string slice.
454///
455/// # Example
456///
457/// ```
458/// use nstd_sys::core::str::{nstd_core_str_byte_len, nstd_core_str_from_raw_cstr_with_null};
459///
460/// let s_str = "Hello, 🌎!\0";
461/// unsafe {
462///     let str = nstd_core_str_from_raw_cstr_with_null(s_str.as_ptr().cast()).unwrap();
463///     assert!(nstd_core_str_byte_len(&str) == s_str.len());
464/// }
465/// ```
466#[inline]
467#[nstdapi]
468pub const fn nstd_core_str_byte_len(str: &NSTDStr) -> NSTDUInt {
469    str.len
470}
471
472/// Gets the `NSTDUnichar` at index `pos` in `str`.
473///
474/// # Note
475///
476/// `pos` does not refer to the byte index of the character, but the `NSTDUnichar` index instead.
477///
478/// # Parameters:
479///
480/// - `const NSTDStr *str` - The string slice to index.
481///
482/// - `NSTDUInt pos` - The index of the character to get.
483///
484/// # Returns
485///
486/// `NSTDOptionalUnichar chr` - The character at index `pos`, or none on error.
487///
488/// # Safety
489///
490/// This operation can cause undefined behavior in the event that `str`'s data is invalid.
491///
492/// # Example
493///
494/// ```
495/// use nstd_sys::core::str::{nstd_core_str_from_raw_cstr, nstd_core_str_get};
496///
497/// let s_str = "🦀🚀🦀!\0";
498/// unsafe {
499///     let str = nstd_core_str_from_raw_cstr(s_str.as_ptr().cast()).unwrap();
500///     assert!(nstd_core_str_get(&str, 1).unwrap() == '🚀'.into());
501/// }
502/// ```
503#[inline]
504#[nstdapi]
505pub unsafe fn nstd_core_str_get(str: &NSTDStr, pos: NSTDUInt) -> NSTDOptionalUnichar {
506    str.as_str()
507        .chars()
508        .nth(pos)
509        .map_or(NSTDOptional::None, |chr| NSTDOptional::Some(chr.into()))
510}
511
512/// Creates a substring of an existing string slice.
513///
514/// # Parameters:
515///
516/// - `const NSTDStr *str` - The string slice to create the new substring from.
517///
518/// - `NSTDURange range` - The bounds of the new substring (indexed by bytes).
519///
520/// # Returns
521///
522/// `NSTDOptionalStr substr` - The new substring on success, or a "none" variant if the
523/// result is not valid UTF-8.
524///
525/// # Panics
526///
527/// This operation can panic under the following circumstances:
528///
529/// - `range.start` is greater than `range.end`.
530///
531/// - `range.end` is greater than `str.len`.
532///
533/// # Safety
534///
535/// `str`'s data must be valid for reads of at least `str.len` consecutive bytes.
536///
537/// # Example
538///
539/// ```
540/// use nstd_sys::core::{
541///     range::NSTDURange,
542///     str::{nstd_core_str_byte_len, nstd_core_str_from_raw_cstr, nstd_core_str_substr},
543/// };
544///
545/// let s_str = "33marrow\0";
546/// unsafe {
547///     let str = nstd_core_str_from_raw_cstr(s_str.as_ptr().cast()).unwrap();
548///     let range = NSTDURange {
549///         start: 2,
550///         end: nstd_core_str_byte_len(&str),
551///     };
552///     let marrow = nstd_core_str_substr(&str, range).unwrap();
553///     assert!(nstd_core_str_byte_len(&marrow) == 6);
554/// }
555/// ```
556#[nstdapi]
557#[allow(clippy::suspicious_operation_groupings)]
558pub const unsafe fn nstd_core_str_substr(str: &NSTDStr, range: NSTDURange) -> NSTDOptionalStr {
559    // Make sure the range is valid for the bounds of `str`.
560    assert!(range.start <= range.end && range.end <= str.len);
561    // Create the byte slice with `range` and use it to create the new string slice.
562    let start = str.ptr.add(range.start).cast();
563    #[allow(clippy::arithmetic_side_effects)]
564    let bytes = nstd_core_slice_new_unchecked(start, 1, 1, range.end - range.start);
565    nstd_core_str_from_bytes(&bytes)
566}
567
568gen_to_primitive!(
569    /// # Example
570    ///
571    /// ```
572    /// use nstd_sys::core::{
573    ///     optional::NSTDOptional,
574    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_f32},
575    /// };
576    ///
577    /// let str = "-420.69\0";
578    /// unsafe {
579    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
580    ///     let v = nstd_core_str_to_f32(&str);
581    ///     assert!(v == NSTDOptional::Some(-420.69));
582    /// }
583    /// ```
584    nstd_core_str_to_f32,
585    NSTDStr,
586    NSTDFloat32,
587    NSTDOptionalFloat32
588);
589gen_to_primitive!(
590    /// # Example
591    ///
592    /// ```
593    /// use nstd_sys::core::{
594    ///     optional::NSTDOptional,
595    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_f64},
596    /// };
597    ///
598    /// let str = "-420.69\0";
599    /// unsafe {
600    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
601    ///     let v = nstd_core_str_to_f64(&str);
602    ///     assert!(v == NSTDOptional::Some(-420.69));
603    /// }
604    /// ```
605    nstd_core_str_to_f64,
606    NSTDStr,
607    NSTDFloat64,
608    NSTDOptionalFloat64
609);
610gen_to_primitive!(
611    /// # Example
612    ///
613    /// ```
614    /// use nstd_sys::core::{
615    ///     optional::NSTDOptional,
616    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_int},
617    /// };
618    ///
619    /// let str = "33\0";
620    /// unsafe {
621    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
622    ///     let v = nstd_core_str_to_int(&str);
623    ///     assert!(v == NSTDOptional::Some(33));
624    /// }
625    /// ```
626    nstd_core_str_to_int,
627    NSTDStr,
628    NSTDInt,
629    NSTDOptionalInt
630);
631gen_to_primitive!(
632    /// # Example
633    ///
634    /// ```
635    /// use nstd_sys::core::{
636    ///     optional::NSTDOptional,
637    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_uint},
638    /// };
639    ///
640    /// let str = "33\0";
641    /// unsafe {
642    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
643    ///     let v = nstd_core_str_to_uint(&str);
644    ///     assert!(v == NSTDOptional::Some(33));
645    /// }
646    /// ```
647    nstd_core_str_to_uint,
648    NSTDStr,
649    NSTDUInt,
650    NSTDOptionalUInt
651);
652gen_to_primitive!(
653    /// # Example
654    ///
655    /// ```
656    /// use nstd_sys::core::{
657    ///     optional::NSTDOptional,
658    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_i8},
659    /// };
660    ///
661    /// let str = "33\0";
662    /// unsafe {
663    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
664    ///     let v = nstd_core_str_to_i8(&str);
665    ///     assert!(v == NSTDOptional::Some(33));
666    /// }
667    /// ```
668    nstd_core_str_to_i8,
669    NSTDStr,
670    NSTDInt8,
671    NSTDOptionalInt8
672);
673gen_to_primitive!(
674    /// # Example
675    ///
676    /// ```
677    /// use nstd_sys::core::{
678    ///     optional::NSTDOptional,
679    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_u8},
680    /// };
681    ///
682    /// let str = "33\0";
683    /// unsafe {
684    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
685    ///     let v = nstd_core_str_to_u8(&str);
686    ///     assert!(v == NSTDOptional::Some(33));
687    /// }
688    /// ```
689    nstd_core_str_to_u8,
690    NSTDStr,
691    NSTDUInt8,
692    NSTDOptionalUInt8
693);
694gen_to_primitive!(
695    /// # Example
696    ///
697    /// ```
698    /// use nstd_sys::core::{
699    ///     optional::NSTDOptional,
700    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_i16},
701    /// };
702    ///
703    /// let str = "33\0";
704    /// unsafe {
705    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
706    ///     let v = nstd_core_str_to_i16(&str);
707    ///     assert!(v == NSTDOptional::Some(33));
708    /// }
709    /// ```
710    nstd_core_str_to_i16,
711    NSTDStr,
712    NSTDInt16,
713    NSTDOptionalInt16
714);
715gen_to_primitive!(
716    /// # Example
717    ///
718    /// ```
719    /// use nstd_sys::core::{
720    ///     optional::NSTDOptional,
721    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_u16},
722    /// };
723    ///
724    /// let str = "33\0";
725    /// unsafe {
726    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
727    ///     let v = nstd_core_str_to_u16(&str);
728    ///     assert!(v == NSTDOptional::Some(33));
729    /// }
730    /// ```
731    nstd_core_str_to_u16,
732    NSTDStr,
733    NSTDUInt16,
734    NSTDOptionalUInt16
735);
736gen_to_primitive!(
737    /// # Example
738    ///
739    /// ```
740    /// use nstd_sys::core::{
741    ///     optional::NSTDOptional,
742    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_i32},
743    /// };
744    ///
745    /// let str = "33\0";
746    /// unsafe {
747    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
748    ///     let v = nstd_core_str_to_i32(&str);
749    ///     assert!(v == NSTDOptional::Some(33));
750    /// }
751    /// ```
752    nstd_core_str_to_i32,
753    NSTDStr,
754    NSTDInt32,
755    NSTDOptionalInt32
756);
757gen_to_primitive!(
758    /// # Example
759    ///
760    /// ```
761    /// use nstd_sys::core::{
762    ///     optional::NSTDOptional,
763    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_u32},
764    /// };
765    ///
766    /// let str = "33\0";
767    /// unsafe {
768    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
769    ///     let v = nstd_core_str_to_u32(&str);
770    ///     assert!(v == NSTDOptional::Some(33));
771    /// }
772    /// ```
773    nstd_core_str_to_u32,
774    NSTDStr,
775    NSTDUInt32,
776    NSTDOptionalUInt32
777);
778gen_to_primitive!(
779    /// # Example
780    ///
781    /// ```
782    /// use nstd_sys::core::{
783    ///     optional::NSTDOptional,
784    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_i64},
785    /// };
786    ///
787    /// let str = "33\0";
788    /// unsafe {
789    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
790    ///     let v = nstd_core_str_to_i64(&str);
791    ///     assert!(v == NSTDOptional::Some(33));
792    /// }
793    /// ```
794    nstd_core_str_to_i64,
795    NSTDStr,
796    NSTDInt64,
797    NSTDOptionalInt64
798);
799gen_to_primitive!(
800    /// # Example
801    ///
802    /// ```
803    /// use nstd_sys::core::{
804    ///     optional::NSTDOptional,
805    ///     str::{nstd_core_str_from_raw_cstr, nstd_core_str_to_u64},
806    /// };
807    ///
808    /// let str = "33\0";
809    /// unsafe {
810    ///     let str = nstd_core_str_from_raw_cstr(str.as_ptr().cast()).unwrap();
811    ///     let v = nstd_core_str_to_u64(&str);
812    ///     assert!(v == NSTDOptional::Some(33));
813    /// }
814    /// ```
815    nstd_core_str_to_u64,
816    NSTDStr,
817    NSTDUInt64,
818    NSTDOptionalUInt64
819);
820
821/// An unowned view into a UTF-8 encoded byte string.
822#[nstdapi]
823pub struct NSTDStrMut {
824    /// A raw pointer to the string's data.
825    ptr: *mut NSTDByte,
826    /// The number of bytes in the string.
827    len: NSTDUInt,
828}
829impl NSTDStrMut {
830    /// Creates a Rust string slice from this [`NSTDStrMut`].
831    ///
832    /// # Safety
833    ///
834    /// This string slice's data must remain valid UTF-8 and left unmodified while the returned
835    /// string slice is in use.
836    #[inline]
837    const unsafe fn as_str(&self) -> &str {
838        let bytes = core::slice::from_raw_parts(self.ptr, self.len);
839        core::str::from_utf8_unchecked(bytes)
840    }
841}
842gen_optional!(NSTDOptionalStrMut, NSTDStrMut);
843
844/// Creates a new instance of an `NSTDStrMut` from a C string slice.
845///
846/// # Parameters:
847///
848/// - `NSTDCStrMut *cstr` - The C string slice to wrap.
849///
850/// # Returns
851///
852/// `NSTDOptionalStrMut str` - The new `NSTDStrMut` instance on success, or a "none" variant if the
853/// result is not valid UTF-8.
854///
855/// # Safety
856///
857/// `cstr`'s data must be valid for reads of at least `cstr.len` consecutive bytes.
858///
859/// # Example
860///
861/// ```
862/// use nstd_sys::core::{
863///     cstr::nstd_core_cstr_mut_from_raw,
864///     str::{nstd_core_str_mut_byte_len, nstd_core_str_mut_from_cstr},
865/// };
866///
867/// let mut s_str = String::from("Hello, world!\0");
868/// unsafe {
869///     let mut cstr = nstd_core_cstr_mut_from_raw(s_str.as_mut_ptr().cast());
870///     let str = nstd_core_str_mut_from_cstr(&mut cstr).unwrap();
871///     assert!(nstd_core_str_mut_byte_len(&str) == 13);
872/// }
873/// ```
874#[nstdapi]
875pub unsafe fn nstd_core_str_mut_from_cstr(cstr: &mut NSTDCStrMut) -> NSTDOptionalStrMut {
876    match core::str::from_utf8(cstr.as_bytes()).is_ok() {
877        true => {
878            let ptr = nstd_core_cstr_mut_as_ptr(cstr).cast();
879            let len = nstd_core_cstr_mut_len(cstr);
880            NSTDOptional::Some(NSTDStrMut { ptr, len })
881        }
882        false => NSTDOptional::None,
883    }
884}
885
886/// Creates a new instance of an `NSTDStrMut` from a C string slice.
887///
888/// # Parameters:
889///
890/// - `NSTDCStrMut *cstr` - The C string slice to wrap.
891///
892/// # Returns
893///
894/// `NSTDStrMut str` - The new `NSTDStrMut` instance.
895///
896/// # Safety
897///
898/// This function does not check to ensure that `cstr` is valid UTF-8. `cstr`'s data must remain
899/// valid while the returned string slice is in use.
900///
901/// # Example
902///
903/// ```
904/// use nstd_sys::core::{
905///     cstr::nstd_core_cstr_mut_from_raw,
906///     str::{nstd_core_str_mut_byte_len, nstd_core_str_mut_from_cstr_unchecked},
907/// };
908///
909/// let mut s_str = String::from("Goodbye, world!\0");
910/// unsafe {
911///     let mut cstr = nstd_core_cstr_mut_from_raw(s_str.as_mut_ptr().cast());
912///     let str = nstd_core_str_mut_from_cstr_unchecked(&mut cstr);
913///     assert!(nstd_core_str_mut_byte_len(&str) == 15);
914/// }
915/// ```
916#[inline]
917#[nstdapi]
918pub unsafe fn nstd_core_str_mut_from_cstr_unchecked(cstr: &mut NSTDCStrMut) -> NSTDStrMut {
919    let ptr = nstd_core_cstr_mut_as_ptr(cstr).cast();
920    let len = nstd_core_cstr_mut_len(cstr);
921    NSTDStrMut { ptr, len }
922}
923
924/// Creates a new `NSTDStrMut` from a raw C string.
925///
926/// # Parameters:
927///
928/// - `NSTDChar *cstr` - The raw C string to wrap.
929///
930/// # Returns
931///
932/// `NSTDOptionalStrMut str` - The new string slice on success or an uninitialized "none" variant
933/// if `cstr` is null, `cstr`'s length exceeds `NSTDInt`'s max value, or `cstr` is not valid UTF-8.
934///
935/// # Safety
936///
937/// `cstr` must point to a character array that is valid for reads up until and including it's
938/// null-terminating byte.
939///
940/// # Example
941///
942/// ```
943/// use nstd_sys::core::str::{nstd_core_str_mut_byte_len, nstd_core_str_mut_from_raw_cstr};
944///
945/// let mut s_str = String::from("Where I live is where I bleed.\0");
946/// unsafe {
947///     let str = nstd_core_str_mut_from_raw_cstr(s_str.as_mut_ptr().cast()).unwrap();
948///     assert!(nstd_core_str_mut_byte_len(&str) == 30);
949/// }
950/// ```
951#[nstdapi]
952pub unsafe fn nstd_core_str_mut_from_raw_cstr(cstr: *mut NSTDChar) -> NSTDOptionalStrMut {
953    if !cstr.is_null() {
954        let len = nstd_core_cstr_raw_len(cstr);
955        if len <= NSTD_INT_MAX {
956            let ptr = cstr.cast();
957            let bytes = core::slice::from_raw_parts(ptr, len);
958            if core::str::from_utf8(bytes).is_ok() {
959                return NSTDOptional::Some(NSTDStrMut { ptr, len });
960            }
961        }
962    }
963    NSTDOptional::None
964}
965
966/// Creates a new `NSTDStrMut` from a raw C string, including the null byte.
967///
968/// # Parameters:
969///
970/// - `NSTDChar *cstr` - The raw C string to wrap.
971///
972/// # Returns
973///
974/// `NSTDOptionalStrMut str` - The new string slice on success or an uninitialized "none" variant
975/// if `cstr` is null, `cstr`'s length exceeds `NSTDInt`'s max value, or `cstr` is not valid UTF-8.
976///
977/// # Safety
978///
979/// `cstr` must point to a character array that is valid for reads up until and including it's
980/// null-terminating byte.
981///
982/// # Example
983///
984/// ```
985/// use nstd_sys::core::str::{
986///     nstd_core_str_mut_byte_len, nstd_core_str_mut_from_raw_cstr_with_null,
987/// };
988///
989/// let mut s_str = String::from("{Hello, world!}}}%\0");
990/// unsafe {
991///     let str = nstd_core_str_mut_from_raw_cstr_with_null(s_str.as_mut_ptr().cast()).unwrap();
992///     assert!(nstd_core_str_mut_byte_len(&str) == 19);
993/// }
994/// ```
995#[nstdapi]
996pub unsafe fn nstd_core_str_mut_from_raw_cstr_with_null(cstr: *mut NSTDChar) -> NSTDOptionalStrMut {
997    if !cstr.is_null() {
998        let len = nstd_core_cstr_raw_len_with_null(cstr);
999        if len <= NSTD_INT_MAX {
1000            let ptr = cstr.cast();
1001            let bytes = core::slice::from_raw_parts(ptr, len);
1002            if core::str::from_utf8(bytes).is_ok() {
1003                return NSTDOptional::Some(NSTDStrMut { ptr, len });
1004            }
1005        }
1006    }
1007    NSTDOptional::None
1008}
1009
1010/// Creates a string slice from raw bytes.
1011///
1012/// # Parameters:
1013///
1014/// - `NSTDSliceMut *bytes` - The UTF-8 encoded byte slice.
1015///
1016/// # Returns
1017///
1018/// `NSTDOptionalStrMut str` - The new string slice on success, or a "none" variant if the
1019/// result is not valid UTF-8.
1020///
1021/// # Safety
1022///
1023/// - `bytes` must remain valid while the returned string slice is in use.
1024///
1025/// - `bytes`'s data must be valid for reads of at least `bytes.len` consecutive bytes.
1026///
1027/// # Example
1028///
1029/// ```
1030/// use nstd_sys::core::{
1031///     slice::nstd_core_slice_mut_new,
1032///     str::{nstd_core_str_mut_byte_len, nstd_core_str_mut_from_bytes},
1033/// };
1034///
1035/// let mut s_str = String::from("Hello, world!\0");
1036/// unsafe {
1037///     let mut bytes =
1038///         nstd_core_slice_mut_new(s_str.as_mut_ptr().cast(), 1, 1, s_str.len()).unwrap();
1039///     let str = nstd_core_str_mut_from_bytes(&mut bytes).unwrap();
1040///     assert!(nstd_core_str_mut_byte_len(&str) == 14);
1041/// }
1042/// ```
1043#[nstdapi]
1044pub unsafe fn nstd_core_str_mut_from_bytes(bytes: &mut NSTDSliceMut) -> NSTDOptionalStrMut {
1045    if let Some(bytes) = bytes.as_slice_mut() {
1046        if core::str::from_utf8(bytes).is_ok() {
1047            return NSTDOptional::Some(NSTDStrMut {
1048                ptr: bytes.as_mut_ptr(),
1049                len: bytes.len(),
1050            });
1051        }
1052    }
1053    NSTDOptional::None
1054}
1055
1056/// Creates a string slice from raw bytes, without checking for UTF-8.
1057///
1058/// # Parameters:
1059///
1060/// - `NSTDSliceMut *bytes` - The UTF-8 encoded byte slice.
1061///
1062/// # Returns
1063///
1064/// `NSTDStrMut str` - The new string slice.
1065///
1066/// # Panics
1067///
1068/// This operation will panic if `bytes`'s stride is not 1.
1069///
1070/// # Safety
1071///
1072/// - This function does not check to ensure that `bytes` are valid UTF-8.
1073///
1074/// - `bytes` must remain valid while the returned string slice is in use.
1075///
1076/// - `bytes`'s data must be valid for reads of at least `bytes.len` consecutive bytes.
1077///
1078/// # Example
1079///
1080/// ```
1081/// use nstd_sys::core::{
1082///     slice::nstd_core_slice_mut_new,
1083///     str::{nstd_core_str_mut_byte_len, nstd_core_str_mut_from_bytes_unchecked},
1084/// };
1085///
1086/// let mut s_str = String::from("Goodbye, world!\0");
1087/// unsafe {
1088///     let mut bytes =
1089///         nstd_core_slice_mut_new(s_str.as_mut_ptr().cast(), 1, 1, s_str.len()).unwrap();
1090///     let str = nstd_core_str_mut_from_bytes_unchecked(&mut bytes);
1091///     assert!(nstd_core_str_mut_byte_len(&str) == 16);
1092/// }
1093/// ```
1094#[inline]
1095#[nstdapi]
1096pub unsafe fn nstd_core_str_mut_from_bytes_unchecked(bytes: &mut NSTDSliceMut) -> NSTDStrMut {
1097    assert!(nstd_core_slice_mut_stride(bytes) == 1);
1098    let ptr = nstd_core_slice_mut_as_ptr(bytes).cast();
1099    let len = nstd_core_slice_mut_len(bytes);
1100    NSTDStrMut { ptr, len }
1101}
1102
1103/// Creates an immutable version of a mutable string slice.
1104///
1105/// # Parameters:
1106///
1107/// - `const NSTDStrMut *str` - The mutable string slice.
1108///
1109/// # Returns
1110///
1111/// `NSTDStr str_const` - The immutable copy of `str`.
1112#[inline]
1113#[nstdapi]
1114pub const fn nstd_core_str_mut_as_const(str: &NSTDStrMut) -> NSTDStr {
1115    let bytes = nstd_core_str_mut_as_bytes(str);
1116    // SAFETY: String slices are UTF-8 encoded.
1117    unsafe { nstd_core_str_from_bytes_unchecked(&bytes) }
1118}
1119
1120/// Returns a C string slice variant of this UTF-8 encoded string slice.
1121///
1122/// # Parameters:
1123///
1124/// - `const NSTDStrMut *str` - The UTF-8 encoded string slice.
1125///
1126/// # Returns
1127///
1128/// `NSTDCStr cstr` - The new C string slice.
1129#[inline]
1130#[nstdapi]
1131pub const fn nstd_core_str_mut_as_cstr(str: &NSTDStrMut) -> NSTDCStr {
1132    // SAFETY: `str.ptr` is never null, string slices are never longer than `NSTDInt`'s max value.
1133    unsafe { nstd_core_cstr_new_unchecked(str.ptr.cast(), str.len) }
1134}
1135
1136/// Returns an immutable byte slice over `str`'s data.
1137///
1138/// # Parameters:
1139///
1140/// - `const NSTDStrMut *str` - The string slice.
1141///
1142/// # Returns
1143///
1144/// `NSTDSlice bytes` - An immutable byte slice over `str`'s data.
1145///
1146/// # Example
1147///
1148/// ```
1149/// use nstd_sys::core::{
1150///     slice::nstd_core_slice_len,
1151///     str::{
1152///         nstd_core_str_mut_as_bytes, nstd_core_str_mut_byte_len, nstd_core_str_mut_from_raw_cstr,
1153///     },
1154/// };
1155///
1156/// let mut s_str = String::from("We won't be alone 🎶\0");
1157/// unsafe {
1158///     let mut str = nstd_core_str_mut_from_raw_cstr(s_str.as_mut_ptr().cast()).unwrap();
1159///     let bytes = nstd_core_str_mut_as_bytes(&str);
1160///     assert!(nstd_core_str_mut_byte_len(&str) == nstd_core_slice_len(&bytes));
1161/// }
1162/// ```
1163#[inline]
1164#[nstdapi]
1165pub const fn nstd_core_str_mut_as_bytes(str: &NSTDStrMut) -> NSTDSlice {
1166    // SAFETY: `str.ptr` is never null, string slice lengths are never greater than `NSTDInt`'s max
1167    // value.
1168    unsafe { nstd_core_slice_new_unchecked(str.ptr.cast(), 1, 1, str.len) }
1169}
1170
1171/// Returns an immutable raw pointer to a string slice's memory.
1172///
1173/// # Parameters:
1174///
1175/// - `const NSTDStrMut *str` - The string slice.
1176///
1177/// # Returns
1178///
1179/// `const NSTDByte *ptr` - A raw pointer to a string slice's memory.
1180#[inline]
1181#[nstdapi]
1182pub const fn nstd_core_str_mut_as_ptr(str: &NSTDStrMut) -> *const NSTDByte {
1183    str.ptr
1184}
1185
1186/// Returns the number of Unicode characters in a string slice.
1187///
1188/// # Parameters:
1189///
1190/// - `const NSTDStrMut *str` - The string slice.
1191///
1192/// # Returns
1193///
1194/// `NSTDUInt len` - The length of the string slice.
1195///
1196/// # Safety
1197///
1198/// This operation can cause undefined behavior in the event that `str`'s data is invalid.
1199///
1200/// # Example
1201///
1202/// ```
1203/// use nstd_sys::core::str::{nstd_core_str_mut_len, nstd_core_str_mut_from_raw_cstr};
1204///
1205/// let mut s_str = String::from("Hello, 🌎!\0");
1206/// unsafe {
1207///     let str = nstd_core_str_mut_from_raw_cstr(s_str.as_mut_ptr().cast()).unwrap();
1208///     assert!(nstd_core_str_mut_len(&str) == 9);
1209/// }
1210/// ```
1211#[inline]
1212#[nstdapi]
1213pub unsafe fn nstd_core_str_mut_len(str: &NSTDStrMut) -> NSTDUInt {
1214    str.as_str().chars().count()
1215}
1216
1217/// Returns the number of bytes a string slice contains.
1218///
1219/// # Parameters:
1220///
1221/// - `const NSTDStrMut *str` - The string slice.
1222///
1223/// # Returns
1224///
1225/// `NSTDUInt byte_len` - The number of bytes in the string slice.
1226///
1227/// # Example
1228///
1229/// ```
1230/// use nstd_sys::core::str::{
1231///     nstd_core_str_mut_byte_len, nstd_core_str_mut_from_raw_cstr_with_null,
1232/// };
1233///
1234/// let mut s_str = String::from("Hello, 🌎!\0");
1235/// unsafe {
1236///     let str = nstd_core_str_mut_from_raw_cstr_with_null(s_str.as_mut_ptr().cast()).unwrap();
1237///     assert!(nstd_core_str_mut_byte_len(&str) == s_str.len());
1238/// }
1239/// ```
1240#[inline]
1241#[nstdapi]
1242pub const fn nstd_core_str_mut_byte_len(str: &NSTDStrMut) -> NSTDUInt {
1243    str.len
1244}
1245
1246/// Gets the `NSTDUnichar` at index `pos` in `str`.
1247///
1248/// # Note
1249///
1250/// `pos` does not refer to the byte index of the character, but the `NSTDUnichar` index instead.
1251///
1252/// # Parameters:
1253///
1254/// - `const NSTDStrMut *str` - The string slice to index.
1255///
1256/// - `NSTDUInt pos` - The index of the character to get.
1257///
1258/// # Returns
1259///
1260/// `NSTDOptionalUnichar chr` - The character at index `pos`, or none on error.
1261///
1262/// # Safety
1263///
1264/// This operation can cause undefined behavior in the event that `str`'s data is invalid.
1265///
1266/// # Example
1267///
1268/// ```
1269/// use nstd_sys::core::str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_get};
1270///
1271/// let mut s_str = String::from("🦀🚀🦀!\0");
1272/// unsafe {
1273///     let str = nstd_core_str_mut_from_raw_cstr(s_str.as_mut_ptr().cast()).unwrap();
1274///     assert!(nstd_core_str_mut_get(&str, 1).unwrap() == '🚀'.into());
1275/// }
1276/// ```
1277#[inline]
1278#[nstdapi]
1279pub unsafe fn nstd_core_str_mut_get(str: &NSTDStrMut, pos: NSTDUInt) -> NSTDOptionalUnichar {
1280    str.as_str()
1281        .chars()
1282        .nth(pos)
1283        .map_or(NSTDOptional::None, |chr| NSTDOptional::Some(chr.into()))
1284}
1285
1286/// Creates a substring of an existing string slice.
1287///
1288/// # Parameters:
1289///
1290/// - `NSTDStrMut *str` - The string slice to create the new substring from.
1291///
1292/// - `NSTDURange range` - The bounds of the new substring (indexed by bytes).
1293///
1294/// # Returns
1295///
1296/// `NSTDOptionalStrMut substr` - The new substring on success, or a "none" variant if the
1297/// result is not valid UTF-8.
1298///
1299/// # Panics
1300///
1301/// This operation can panic under the following circumstances:
1302///
1303/// - `range.start` is greater than `range.end`.
1304///
1305/// - `range.end` is greater than `str.len`.
1306///
1307/// # Safety
1308///
1309/// `str`'s data must be valid for reads of at least `str.len` consecutive bytes.
1310///
1311/// # Example
1312///
1313/// ```
1314/// use nstd_sys::core::{
1315///     range::NSTDURange,
1316///     str::{
1317///         nstd_core_str_mut_byte_len, nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_substr,
1318///     },
1319/// };
1320///
1321/// let mut s_str = String::from("33marrow\0");
1322/// unsafe {
1323///     let mut str = nstd_core_str_mut_from_raw_cstr(s_str.as_mut_ptr().cast()).unwrap();
1324///     let range = NSTDURange {
1325///         start: 2,
1326///         end: nstd_core_str_mut_byte_len(&str),
1327///     };
1328///     let marrow = nstd_core_str_mut_substr(&mut str, range).unwrap();
1329///     assert!(nstd_core_str_mut_byte_len(&marrow) == 6);
1330/// }
1331/// ```
1332#[nstdapi]
1333#[allow(clippy::suspicious_operation_groupings)]
1334pub unsafe fn nstd_core_str_mut_substr(
1335    str: &mut NSTDStrMut,
1336    range: NSTDURange,
1337) -> NSTDOptionalStrMut {
1338    // Make sure the range is valid for the bounds of `str`.
1339    assert!(range.start <= range.end && range.end <= str.len);
1340    // Create the byte slice with `range` and use it to create the new string slice.
1341    let start = str.ptr.add(range.start).cast();
1342    #[allow(clippy::arithmetic_side_effects)]
1343    let mut bytes = nstd_core_slice_mut_new_unchecked(start, 1, 1, range.end - range.start);
1344    nstd_core_str_mut_from_bytes(&mut bytes)
1345}
1346
1347gen_to_primitive!(
1348    /// # Example
1349    ///
1350    /// ```
1351    /// use nstd_sys::core::{
1352    ///     optional::NSTDOptional,
1353    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_f32},
1354    /// };
1355    ///
1356    /// let mut str = String::from("-420.69\0");
1357    /// unsafe {
1358    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1359    ///     let v = nstd_core_str_mut_to_f32(&str);
1360    ///     assert!(v == NSTDOptional::Some(-420.69));
1361    /// }
1362    /// ```
1363    nstd_core_str_mut_to_f32,
1364    NSTDStrMut,
1365    NSTDFloat32,
1366    NSTDOptionalFloat32
1367);
1368gen_to_primitive!(
1369    /// # Example
1370    ///
1371    /// ```
1372    /// use nstd_sys::core::{
1373    ///     optional::NSTDOptional,
1374    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_f64},
1375    /// };
1376    ///
1377    /// let mut str = String::from("-420.69\0");
1378    /// unsafe {
1379    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1380    ///     let v = nstd_core_str_mut_to_f64(&str);
1381    ///     assert!(v == NSTDOptional::Some(-420.69));
1382    /// }
1383    /// ```
1384    nstd_core_str_mut_to_f64,
1385    NSTDStrMut,
1386    NSTDFloat64,
1387    NSTDOptionalFloat64
1388);
1389gen_to_primitive!(
1390    /// # Example
1391    ///
1392    /// ```
1393    /// use nstd_sys::core::{
1394    ///     optional::NSTDOptional,
1395    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_int},
1396    /// };
1397    ///
1398    /// let mut str = String::from("33\0");
1399    /// unsafe {
1400    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1401    ///     let v = nstd_core_str_mut_to_int(&str);
1402    ///     assert!(v == NSTDOptional::Some(33));
1403    /// }
1404    /// ```
1405    nstd_core_str_mut_to_int,
1406    NSTDStrMut,
1407    NSTDInt,
1408    NSTDOptionalInt
1409);
1410gen_to_primitive!(
1411    /// # Example
1412    ///
1413    /// ```
1414    /// use nstd_sys::core::{
1415    ///     optional::NSTDOptional,
1416    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_uint},
1417    /// };
1418    ///
1419    /// let mut str = String::from("33\0");
1420    /// unsafe {
1421    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1422    ///     let v = nstd_core_str_mut_to_uint(&str);
1423    ///     assert!(v == NSTDOptional::Some(33));
1424    /// }
1425    /// ```
1426    nstd_core_str_mut_to_uint,
1427    NSTDStrMut,
1428    NSTDUInt,
1429    NSTDOptionalUInt
1430);
1431gen_to_primitive!(
1432    /// # Example
1433    ///
1434    /// ```
1435    /// use nstd_sys::core::{
1436    ///     optional::NSTDOptional,
1437    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_i8},
1438    /// };
1439    ///
1440    /// let mut str = String::from("33\0");
1441    /// unsafe {
1442    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1443    ///     let v = nstd_core_str_mut_to_i8(&str);
1444    ///     assert!(v == NSTDOptional::Some(33));
1445    /// }
1446    /// ```
1447    nstd_core_str_mut_to_i8,
1448    NSTDStrMut,
1449    NSTDInt8,
1450    NSTDOptionalInt8
1451);
1452gen_to_primitive!(
1453    /// # Example
1454    ///
1455    /// ```
1456    /// use nstd_sys::core::{
1457    ///     optional::NSTDOptional,
1458    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_u8},
1459    /// };
1460    ///
1461    /// let mut str = String::from("33\0");
1462    /// unsafe {
1463    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1464    ///     let v = nstd_core_str_mut_to_u8(&str);
1465    ///     assert!(v == NSTDOptional::Some(33));
1466    /// }
1467    /// ```
1468    nstd_core_str_mut_to_u8,
1469    NSTDStrMut,
1470    NSTDUInt8,
1471    NSTDOptionalUInt8
1472);
1473gen_to_primitive!(
1474    /// # Example
1475    ///
1476    /// ```
1477    /// use nstd_sys::core::{
1478    ///     optional::NSTDOptional,
1479    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_i16},
1480    /// };
1481    ///
1482    /// let mut str = String::from("33\0");
1483    /// unsafe {
1484    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1485    ///     let v = nstd_core_str_mut_to_i16(&str);
1486    ///     assert!(v == NSTDOptional::Some(33));
1487    /// }
1488    /// ```
1489    nstd_core_str_mut_to_i16,
1490    NSTDStrMut,
1491    NSTDInt16,
1492    NSTDOptionalInt16
1493);
1494gen_to_primitive!(
1495    /// # Example
1496    ///
1497    /// ```
1498    /// use nstd_sys::core::{
1499    ///     optional::NSTDOptional,
1500    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_u16},
1501    /// };
1502    ///
1503    /// let mut str = String::from("33\0");
1504    /// unsafe {
1505    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1506    ///     let v = nstd_core_str_mut_to_u16(&str);
1507    ///     assert!(v == NSTDOptional::Some(33));
1508    /// }
1509    /// ```
1510    nstd_core_str_mut_to_u16,
1511    NSTDStrMut,
1512    NSTDUInt16,
1513    NSTDOptionalUInt16
1514);
1515gen_to_primitive!(
1516    /// # Example
1517    ///
1518    /// ```
1519    /// use nstd_sys::core::{
1520    ///     optional::NSTDOptional,
1521    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_i32},
1522    /// };
1523    ///
1524    /// let mut str = String::from("33\0");
1525    /// unsafe {
1526    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1527    ///     let v = nstd_core_str_mut_to_i32(&str);
1528    ///     assert!(v == NSTDOptional::Some(33));
1529    /// }
1530    /// ```
1531    nstd_core_str_mut_to_i32,
1532    NSTDStrMut,
1533    NSTDInt32,
1534    NSTDOptionalInt32
1535);
1536gen_to_primitive!(
1537    /// # Example
1538    ///
1539    /// ```
1540    /// use nstd_sys::core::{
1541    ///     optional::NSTDOptional,
1542    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_u32},
1543    /// };
1544    ///
1545    /// let mut str = String::from("33\0");
1546    /// unsafe {
1547    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1548    ///     let v = nstd_core_str_mut_to_u32(&str);
1549    ///     assert!(v == NSTDOptional::Some(33));
1550    /// }
1551    /// ```
1552    nstd_core_str_mut_to_u32,
1553    NSTDStrMut,
1554    NSTDUInt32,
1555    NSTDOptionalUInt32
1556);
1557gen_to_primitive!(
1558    /// # Example
1559    ///
1560    /// ```
1561    /// use nstd_sys::core::{
1562    ///     optional::NSTDOptional,
1563    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_i64},
1564    /// };
1565    ///
1566    /// let mut str = String::from("33\0");
1567    /// unsafe {
1568    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1569    ///     let v = nstd_core_str_mut_to_i64(&str);
1570    ///     assert!(v == NSTDOptional::Some(33));
1571    /// }
1572    /// ```
1573    nstd_core_str_mut_to_i64,
1574    NSTDStrMut,
1575    NSTDInt64,
1576    NSTDOptionalInt64
1577);
1578gen_to_primitive!(
1579    /// # Example
1580    ///
1581    /// ```
1582    /// use nstd_sys::core::{
1583    ///     optional::NSTDOptional,
1584    ///     str::{nstd_core_str_mut_from_raw_cstr, nstd_core_str_mut_to_u64},
1585    /// };
1586    ///
1587    /// let mut str = String::from("33\0");
1588    /// unsafe {
1589    ///     let str = nstd_core_str_mut_from_raw_cstr(str.as_mut_ptr().cast()).unwrap();
1590    ///     let v = nstd_core_str_mut_to_u64(&str);
1591    ///     assert!(v == NSTDOptional::Some(33));
1592    /// }
1593    /// ```
1594    nstd_core_str_mut_to_u64,
1595    NSTDStrMut,
1596    NSTDUInt64,
1597    NSTDOptionalUInt64
1598);