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);