Skip to main content

non_empty_str/
str.rs

1//! Non-empty [`str`].
2
3#[cfg(feature = "std")]
4use std::{ffi::OsStr, path::Path};
5
6use core::{
7    fmt,
8    hash::{Hash, Hasher},
9    ops::{Deref, DerefMut, Index, IndexMut},
10    ptr,
11    slice::SliceIndex,
12    str::Utf8Error,
13};
14
15use non_empty_slice::{EmptySlice, NonEmptyBytes};
16use non_zero_size::Size;
17use thiserror::Error;
18
19use crate::{
20    internals::{Bytes, MutBytes, RawBytes, attempt, map_error},
21    iter::{
22        Bytes as BytesIter, CharIndices, Chars, EncodeUtf16, EscapeDebug, EscapeDefault,
23        EscapeUnicode, Lines, SplitAsciiWhitespace, SplitWhitespace,
24    },
25};
26
27/// The error message used when the string is empty.
28pub const EMPTY_STR: &str = "the string is empty";
29
30/// Represents errors returned when received strings are empty.
31#[derive(Debug, Error)]
32#[error("{EMPTY_STR}")]
33pub struct EmptyStr;
34
35/// Represents errors returned when the received non-empty bytes are not valid UTF-8.
36///
37/// This is returned from [`from_non_empty_utf8`] and [`from_non_empty_utf8_mut`] methods
38/// on [`NonEmptyStr`].
39///
40/// [`from_non_empty_utf8`]: NonEmptyStr::from_non_empty_utf8
41/// [`from_non_empty_utf8_mut`]: NonEmptyStr::from_non_empty_utf8_mut
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
43#[error("{error}")]
44pub struct NonEmptyUtf8Error {
45    #[from]
46    #[source]
47    error: Utf8Error,
48}
49
50impl NonEmptyUtf8Error {
51    /// Constructs [`Self`].
52    #[must_use]
53    pub const fn new(error: Utf8Error) -> Self {
54        Self { error }
55    }
56
57    /// Returns the contained [`Utf8Error`].
58    #[must_use]
59    pub const fn get(self) -> Utf8Error {
60        self.error
61    }
62}
63
64/// Represents errors returned when the received bytes are either empty or not valid UTF-8.
65///
66/// This is returned from [`from_utf8`] and [`from_utf8_mut`] methods on [`NonEmptyStr`].
67///
68/// [`from_utf8`]: NonEmptyStr::from_utf8
69/// [`from_utf8_mut`]: NonEmptyStr::from_utf8_mut
70#[derive(Debug, Error)]
71#[error(transparent)]
72pub enum MaybeEmptyUtf8Error {
73    /// The received bytes are empty.
74    Empty(#[from] EmptySlice),
75    /// The received bytes are non-empty, but not valid UTF-8.
76    Utf8(#[from] NonEmptyUtf8Error),
77}
78
79/// Parsing values from non-empty strings.
80pub trait FromNonEmptyStr: Sized {
81    /// The associated error type returned when parsing fails.
82    type Error;
83
84    /// Parses [`Self`] from the given non-empty string.
85    ///
86    /// # Errors
87    ///
88    /// Returns [`Self::Error`] if parsing fails.
89    fn from_non_empty_str(string: &NonEmptyStr) -> Result<Self, Self::Error>;
90}
91
92/// Represents non-empty [`str`] values.
93#[derive(Debug)]
94#[repr(transparent)]
95pub struct NonEmptyStr {
96    inner: str,
97}
98
99impl Hash for NonEmptyStr {
100    fn hash<H: Hasher>(&self, state: &mut H) {
101        self.as_str().hash(state);
102    }
103}
104
105impl fmt::Display for NonEmptyStr {
106    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
107        self.as_str().fmt(formatter)
108    }
109}
110
111impl<'s> TryFrom<&'s str> for &'s NonEmptyStr {
112    type Error = EmptyStr;
113
114    fn try_from(string: &'s str) -> Result<Self, Self::Error> {
115        NonEmptyStr::try_from_str(string)
116    }
117}
118
119impl<'s> TryFrom<&'s mut str> for &'s mut NonEmptyStr {
120    type Error = EmptyStr;
121
122    fn try_from(string: &'s mut str) -> Result<Self, Self::Error> {
123        NonEmptyStr::try_from_mut_str(string)
124    }
125}
126
127impl<'s> From<&'s NonEmptyStr> for &'s str {
128    fn from(string: &'s NonEmptyStr) -> Self {
129        string.as_str()
130    }
131}
132
133impl<'b> TryFrom<&'b NonEmptyBytes> for &'b NonEmptyStr {
134    type Error = NonEmptyUtf8Error;
135
136    fn try_from(non_empty: &'b NonEmptyBytes) -> Result<Self, Self::Error> {
137        NonEmptyStr::from_non_empty_utf8(non_empty)
138    }
139}
140
141impl<'b> TryFrom<&'b mut NonEmptyBytes> for &'b mut NonEmptyStr {
142    type Error = NonEmptyUtf8Error;
143
144    fn try_from(non_empty: &'b mut NonEmptyBytes) -> Result<Self, Self::Error> {
145        NonEmptyStr::from_non_empty_utf8_mut(non_empty)
146    }
147}
148
149impl<'b> TryFrom<&'b Bytes> for &'b NonEmptyStr {
150    type Error = MaybeEmptyUtf8Error;
151
152    fn try_from(bytes: &'b Bytes) -> Result<Self, Self::Error> {
153        NonEmptyStr::from_utf8(bytes)
154    }
155}
156
157impl<'b> TryFrom<&'b mut Bytes> for &'b mut NonEmptyStr {
158    type Error = MaybeEmptyUtf8Error;
159
160    fn try_from(bytes: &'b mut Bytes) -> Result<Self, Self::Error> {
161        NonEmptyStr::from_utf8_mut(bytes)
162    }
163}
164
165impl<'s> From<&'s mut NonEmptyStr> for &'s mut str {
166    fn from(string: &'s mut NonEmptyStr) -> Self {
167        string.as_mut_str()
168    }
169}
170
171impl AsRef<Self> for NonEmptyStr {
172    fn as_ref(&self) -> &Self {
173        self
174    }
175}
176
177impl AsRef<str> for NonEmptyStr {
178    fn as_ref(&self) -> &str {
179        self.as_str()
180    }
181}
182
183impl AsMut<Self> for NonEmptyStr {
184    fn as_mut(&mut self) -> &mut Self {
185        self
186    }
187}
188
189impl AsMut<str> for NonEmptyStr {
190    fn as_mut(&mut self) -> &mut str {
191        self.as_mut_str()
192    }
193}
194
195impl AsRef<NonEmptyBytes> for NonEmptyStr {
196    fn as_ref(&self) -> &NonEmptyBytes {
197        self.as_non_empty_bytes()
198    }
199}
200
201impl AsRef<Bytes> for NonEmptyStr {
202    fn as_ref(&self) -> &Bytes {
203        self.as_bytes()
204    }
205}
206
207#[cfg(feature = "std")]
208impl AsRef<OsStr> for NonEmptyStr {
209    fn as_ref(&self) -> &OsStr {
210        self.as_str().as_ref()
211    }
212}
213
214#[cfg(feature = "std")]
215impl AsRef<Path> for NonEmptyStr {
216    fn as_ref(&self) -> &Path {
217        self.as_str().as_ref()
218    }
219}
220
221impl Deref for NonEmptyStr {
222    type Target = str;
223
224    fn deref(&self) -> &Self::Target {
225        self.as_str()
226    }
227}
228
229impl DerefMut for NonEmptyStr {
230    fn deref_mut(&mut self) -> &mut Self::Target {
231        self.as_mut_str()
232    }
233}
234
235impl<I: SliceIndex<str>> Index<I> for NonEmptyStr {
236    type Output = I::Output;
237
238    fn index(&self, index: I) -> &Self::Output {
239        self.as_str().index(index)
240    }
241}
242
243impl<I: SliceIndex<str>> IndexMut<I> for NonEmptyStr {
244    fn index_mut(&mut self, index: I) -> &mut Self::Output {
245        self.as_mut_str().index_mut(index)
246    }
247}
248
249impl NonEmptyStr {
250    /// Constructs [`Self`] from anything that can be converted to string, provided it is non-empty.
251    ///
252    /// Prefer [`try_from_str`] if only [`str`] is used, as this allows for `const` evaluation.
253    ///
254    /// # Errors
255    ///
256    /// Returns [`EmptyStr`] if the string is empty.
257    ///
258    /// [`try_from_str`]: Self::try_from_str
259    pub fn try_new<S: AsRef<str> + ?Sized>(string: &S) -> Result<&Self, EmptyStr> {
260        Self::try_from_str(string.as_ref())
261    }
262
263    /// Constructs [`Self`] from anything that can be mutably converted to string,
264    /// provided it is non-empty.
265    ///
266    /// Prefer [`try_from_mut_str`] if only [`str`] is used, as this allows for `const` evaluation.
267    ///
268    /// # Errors
269    ///
270    /// Returns [`EmptyStr`] if the string is empty.
271    ///
272    /// [`try_from_mut_str`]: Self::try_from_mut_str
273    pub fn try_new_mut<S: AsMut<str> + ?Sized>(string: &mut S) -> Result<&mut Self, EmptyStr> {
274        Self::try_from_mut_str(string.as_mut())
275    }
276
277    /// Similar to [`try_new`], but the error is discarded.
278    ///
279    /// Prefer [`from_str`] if only [`str`] is used, as this allows for `const` evaluation.
280    ///
281    /// # Examples
282    ///
283    /// ```
284    /// use non_empty_str::NonEmptyStr;
285    ///
286    /// let non_empty = NonEmptyStr::new("Hello, world!").unwrap();
287    ///
288    /// // `NonEmptyStr` is `AsRef<str>`, so it can also be used!
289    /// let from_non_empty = NonEmptyStr::new(non_empty).unwrap();
290    /// ```
291    ///
292    /// [`try_new`]: Self::try_new
293    /// [`from_str`]: Self::from_str
294    pub fn new<S: AsRef<str> + ?Sized>(string: &S) -> Option<&Self> {
295        Self::from_str(string.as_ref())
296    }
297
298    /// Similar to [`try_new_mut`], but the error is discarded.
299    ///
300    /// Prefer [`from_mut_str`] if only [`str`] is used, as this allows for `const` evaluation.
301    ///
302    /// [`try_new_mut`]: Self::try_new_mut
303    /// [`from_mut_str`]: Self::from_mut_str
304    pub fn new_mut<S: AsMut<str> + ?Sized>(string: &mut S) -> Option<&mut Self> {
305        Self::from_mut_str(string.as_mut())
306    }
307
308    /// Constructs [`Self`] from anything that can be converted to string, without doing any checks.
309    ///
310    /// Prefer [`from_str_unchecked`] if only [`str`] is used; this allows for `const` evaluation.
311    ///
312    /// # Safety
313    ///
314    /// The caller must ensure that the string is non-empty.
315    ///
316    /// [`from_str_unchecked`]: Self::from_str_unchecked
317    #[must_use]
318    pub unsafe fn new_unchecked<S: AsRef<str> + ?Sized>(string: &S) -> &Self {
319        // SAFETY: the caller must ensure that the string is non-empty
320        unsafe { Self::from_str_unchecked(string.as_ref()) }
321    }
322
323    /// Constructs [`Self`] from anything that can be mutably converted to string,
324    /// without doing any checks.
325    ///
326    /// Prefer [`from_mut_str_unchecked`] if only [`str`] is used;
327    /// this allows for `const` evaluation.
328    ///
329    /// # Safety
330    ///
331    /// The caller must ensure that the string is non-empty.
332    ///
333    /// [`from_mut_str_unchecked`]: Self::from_mut_str_unchecked
334    pub unsafe fn new_unchecked_mut<S: AsMut<str> + ?Sized>(string: &mut S) -> &mut Self {
335        // SAFETY: the caller must ensure that the string is non-empty
336        unsafe { Self::from_mut_str_unchecked(string.as_mut()) }
337    }
338
339    /// Constructs [`Self`] from [`str`], provided the string is non-empty.
340    ///
341    /// # Errors
342    ///
343    /// Returns [`EmptyStr`] if the string is empty.
344    pub const fn try_from_str(string: &str) -> Result<&Self, EmptyStr> {
345        if string.is_empty() {
346            return Err(EmptyStr);
347        }
348
349        // SAFETY: the string is non-empty at this point
350        Ok(unsafe { Self::from_str_unchecked(string) })
351    }
352
353    /// Constructs [`Self`] from mutable [`str`], provided the string is non-empty.
354    ///
355    /// # Errors
356    ///
357    /// Returns [`EmptyStr`] if the string is empty.
358    pub const fn try_from_mut_str(string: &mut str) -> Result<&mut Self, EmptyStr> {
359        if string.is_empty() {
360            return Err(EmptyStr);
361        }
362
363        // SAFETY: the string is non-empty at this point
364        Ok(unsafe { Self::from_mut_str_unchecked(string) })
365    }
366
367    /// Similar to [`try_from_str`], but the error is discarded.
368    ///
369    /// # Examples
370    ///
371    /// Basic snippet:
372    ///
373    /// ```
374    /// use non_empty_str::NonEmptyStr;
375    ///
376    /// let message = NonEmptyStr::from_str("Hello, world!").unwrap();
377    /// ```
378    ///
379    /// [`None`] is returned if the string is empty, therefore the following snippet panics:
380    ///
381    /// ```should_panic
382    /// use non_empty_str::NonEmptyStr;
383    ///
384    /// let never = NonEmptyStr::from_str("").unwrap();
385    /// ```
386    ///
387    /// [`try_from_str`]: Self::try_from_str
388    #[must_use]
389    pub const fn from_str(string: &str) -> Option<&Self> {
390        if string.is_empty() {
391            return None;
392        }
393
394        // SAFETY: the string is non-empty at this point
395        Some(unsafe { Self::from_str_unchecked(string) })
396    }
397
398    /// Similar to [`try_from_mut_str`], but the error is discarded.
399    ///
400    /// [`try_from_mut_str`]: Self::try_from_mut_str
401    pub const fn from_mut_str(string: &mut str) -> Option<&mut Self> {
402        if string.is_empty() {
403            return None;
404        }
405
406        // SAFETY: the string is non-empty at this point
407        Some(unsafe { Self::from_mut_str_unchecked(string) })
408    }
409
410    /// Constructs [`Self`] from [`str`], without checking if the string is empty.
411    ///
412    /// # Safety
413    ///
414    /// The caller must ensure that the string is non-empty.
415    #[must_use]
416    pub const unsafe fn from_str_unchecked(string: &str) -> &Self {
417        debug_assert!(!string.is_empty());
418
419        // SAFETY: the caller must ensure that the string is non-empty
420        // `Self` is `repr(transparent)`, so it is safe to transmute
421        unsafe { &*(ptr::from_ref(string) as *const Self) }
422    }
423
424    /// Constructs [`Self`] from mutable [`str`], without checking if the string is empty.
425    ///
426    /// # Safety
427    ///
428    /// The caller must ensure that the string is non-empty.
429    pub const unsafe fn from_mut_str_unchecked(string: &mut str) -> &mut Self {
430        debug_assert!(!string.is_empty());
431
432        // SAFETY: the caller must ensure that the string is non-empty
433        // `Self` is `repr(transparent)`, so it is safe to transmute
434        unsafe { &mut *(ptr::from_mut(string) as *mut Self) }
435    }
436
437    #[cfg(feature = "unsafe-assert")]
438    const fn assert_non_empty(&self) {
439        use core::hint::assert_unchecked;
440
441        // SAFETY: the string is non-empty by construction
442        unsafe {
443            assert_unchecked(!self.as_str_no_assert().is_empty());
444        }
445    }
446
447    const fn as_str_no_assert(&self) -> &str {
448        &self.inner
449    }
450
451    const fn as_mut_str_no_assert(&mut self) -> &mut str {
452        &mut self.inner
453    }
454
455    /// Returns the contained string.
456    ///
457    /// # Examples
458    ///
459    /// ```
460    /// use non_empty_str::NonEmptyStr;
461    ///
462    /// let string = "Hello, world!";
463    ///
464    /// let non_empty = NonEmptyStr::from_str(string).unwrap();
465    ///
466    /// assert_eq!(non_empty.as_str(), string);
467    /// ```
468    #[must_use]
469    pub const fn as_str(&self) -> &str {
470        #[cfg(feature = "unsafe-assert")]
471        self.assert_non_empty();
472
473        self.as_str_no_assert()
474    }
475
476    /// Returns the contained mutable string.
477    #[must_use]
478    pub const fn as_mut_str(&mut self) -> &mut str {
479        #[cfg(feature = "unsafe-assert")]
480        self.assert_non_empty();
481
482        self.as_mut_str_no_assert()
483    }
484
485    /// Checks if the string is empty. Always returns [`false`].
486    ///
487    /// This method is deprecated since the string is never empty.
488    #[deprecated = "this string is never empty"]
489    #[must_use]
490    pub const fn is_empty(&self) -> bool {
491        false
492    }
493
494    /// Returns the length of the string in bytes as [`Size`].
495    #[must_use]
496    pub const fn len(&self) -> Size {
497        let len = self.as_str().len();
498
499        // SAFETY: the string is non-empty by construction, so its length is non-zero
500        unsafe { Size::new_unchecked(len) }
501    }
502
503    /// Returns the underlying bytes of the string.
504    #[must_use]
505    pub const fn as_bytes(&self) -> &Bytes {
506        self.as_str().as_bytes()
507    }
508
509    /// Returns the underlying mutable bytes of the string.
510    ///
511    /// # Safety
512    ///
513    /// The caller must ensure that the bytes remain valid UTF-8.
514    pub const unsafe fn as_bytes_mut(&mut self) -> &mut Bytes {
515        // SAFETY: the caller must ensure that the bytes remain valid UTF-8
516        unsafe { self.as_mut_str().as_bytes_mut() }
517    }
518
519    /// Returns the underlying bytes of the string as [`NonEmptyBytes`].
520    #[must_use]
521    pub const fn as_non_empty_bytes(&self) -> &NonEmptyBytes {
522        // SAFETY: the string is non-empty by construction, so are its bytes
523        unsafe { NonEmptyBytes::from_slice_unchecked(self.as_bytes()) }
524    }
525
526    /// Returns the underlying mutable bytes of the string as [`NonEmptyBytes`].
527    ///
528    /// # Safety
529    ///
530    /// The caller must ensure that the bytes remain valid UTF-8.
531    pub const unsafe fn as_non_empty_bytes_mut(&mut self) -> &mut NonEmptyBytes {
532        // SAFETY: the caller must ensure that the bytes remain valid UTF-8
533        // moreover, the string is non-empty by construction, so are its bytes
534        unsafe { NonEmptyBytes::from_mut_slice_unchecked(self.as_bytes_mut()) }
535    }
536
537    /// Converts given bytes to non-empty string, provided the bytes are non-empty and valid UTF-8.
538    ///
539    /// # Errors
540    ///
541    /// Returns [`MaybeEmptyUtf8Error`] if the bytes are either empty or not valid UTF-8.
542    pub const fn from_utf8(bytes: &Bytes) -> Result<&Self, MaybeEmptyUtf8Error> {
543        let non_empty = attempt!(
544            map_error!(NonEmptyBytes::try_from_slice(bytes) => MaybeEmptyUtf8Error::Empty)
545        );
546
547        map_error!(Self::from_non_empty_utf8(non_empty) => MaybeEmptyUtf8Error::Utf8)
548    }
549
550    /// Converts given mutable bytes to non-empty string, provided the bytes
551    /// are non-empty and valid UTF-8.
552    ///
553    /// # Errors
554    ///
555    /// Returns [`MaybeEmptyUtf8Error`] if the bytes are either empty or not valid UTF-8.
556    pub const fn from_utf8_mut(bytes: &mut Bytes) -> Result<&mut Self, MaybeEmptyUtf8Error> {
557        let non_empty = attempt!(
558            map_error!(NonEmptyBytes::try_from_mut_slice(bytes) => MaybeEmptyUtf8Error::Empty)
559        );
560
561        map_error!(Self::from_non_empty_utf8_mut(non_empty) => MaybeEmptyUtf8Error::Utf8)
562    }
563
564    /// Converts given non-empty bytes to non-empty string, provided the bytes are valid UTF-8.
565    ///
566    /// # Errors
567    ///
568    /// Returns [`NonEmptyUtf8Error`] if the bytes are not valid UTF-8.
569    pub const fn from_non_empty_utf8(
570        non_empty: &NonEmptyBytes,
571    ) -> Result<&Self, NonEmptyUtf8Error> {
572        let string =
573            attempt!(map_error!(str::from_utf8(non_empty.as_slice()) => NonEmptyUtf8Error::new));
574
575        // SAFETY: the bytes are non-empty by construction, so is the resulting string
576        Ok(unsafe { Self::from_str_unchecked(string) })
577    }
578
579    /// Converts given mutable non-empty bytes to non-empty string,
580    /// provided the bytes are valid UTF-8.
581    ///
582    /// # Errors
583    ///
584    /// Returns [`NonEmptyUtf8Error`] if the bytes are not valid UTF-8.
585    pub const fn from_non_empty_utf8_mut(
586        non_empty: &mut NonEmptyBytes,
587    ) -> Result<&mut Self, NonEmptyUtf8Error> {
588        let string = attempt!(
589            map_error!(str::from_utf8_mut(non_empty.as_mut_slice()) => NonEmptyUtf8Error::new)
590        );
591
592        // SAFETY: the bytes are non-empty by construction, so is the resulting string
593        Ok(unsafe { Self::from_mut_str_unchecked(string) })
594    }
595
596    /// Converts given non-empty bytes to non-empty string without checking for UTF-8 validity.
597    ///
598    /// # Safety
599    ///
600    /// The caller must ensure that the bytes are valid UTF-8.
601    #[must_use]
602    pub const unsafe fn from_non_empty_utf8_unchecked(non_empty: &NonEmptyBytes) -> &Self {
603        // SAFETY: the caller must ensure that the bytes are valid UTF-8
604        // moreover, the bytes are non-empty by construction
605        unsafe { Self::from_utf8_unchecked(non_empty.as_slice()) }
606    }
607
608    /// Converts given mutable non-empty bytes to non-empty string
609    /// without checking for UTF-8 validity.
610    ///
611    /// # Safety
612    ///
613    /// The caller must ensure that the bytes are valid UTF-8.
614    pub const unsafe fn from_non_empty_utf8_unchecked_mut(
615        non_empty: &mut NonEmptyBytes,
616    ) -> &mut Self {
617        // SAFETY: the caller must ensure that the bytes are valid UTF-8
618        // moreover, the bytes are non-empty by construction
619        unsafe { Self::from_utf8_unchecked_mut(non_empty.as_mut_slice()) }
620    }
621
622    /// Converts given bytes to non-empty string without checking for emptiness or UTF-8 validity.
623    ///
624    /// # Safety
625    ///
626    /// The caller must ensure that the bytes are valid UTF-8 and non-empty.
627    #[must_use]
628    pub const unsafe fn from_utf8_unchecked(bytes: &Bytes) -> &Self {
629        // SAFETY: the caller must ensure that the bytes are valid UTF-8 and non-empty
630        unsafe { Self::from_str_unchecked(str::from_utf8_unchecked(bytes)) }
631    }
632
633    /// Converts given mutable bytes to non-empty string
634    /// without checking for emptiness or UTF-8 validity.
635    ///
636    /// # Safety
637    ///
638    /// The caller must ensure that the bytes are valid UTF-8 and non-empty.
639    pub const unsafe fn from_utf8_unchecked_mut(bytes: &mut Bytes) -> &mut Self {
640        // SAFETY: the caller must ensure that the bytes are valid UTF-8 and non-empty
641        unsafe { Self::from_mut_str_unchecked(str::from_utf8_unchecked_mut(bytes)) }
642    }
643
644    /// Returns non-empty iterators over the bytes in this string.
645    #[must_use]
646    pub const fn bytes(&self) -> BytesIter<'_> {
647        BytesIter::new(self)
648    }
649
650    /// Returns non-empty iterators over the characters in this string.
651    #[must_use]
652    pub const fn chars(&self) -> Chars<'_> {
653        Chars::new(self)
654    }
655
656    /// Returns non-empty iterators over the characters and their positions in this string.
657    #[must_use]
658    pub const fn char_indices(&self) -> CharIndices<'_> {
659        CharIndices::new(self)
660    }
661
662    /// Returns non-empty iterators over the UTF-16 encoding of this string.
663    #[must_use]
664    pub const fn encode_utf16(&self) -> EncodeUtf16<'_> {
665        EncodeUtf16::new(self)
666    }
667
668    /// Returns non-empty iterators over the debug-escaped characters in this string.
669    #[must_use]
670    pub const fn escape_debug(&self) -> EscapeDebug<'_> {
671        EscapeDebug::new(self)
672    }
673
674    /// Returns non-empty iterators over the default-escaped characters in this string.
675    #[must_use]
676    pub const fn escape_default(&self) -> EscapeDefault<'_> {
677        EscapeDefault::new(self)
678    }
679
680    /// Returns non-empty iterators over the Unicode-escaped characters in this string.
681    #[must_use]
682    pub const fn escape_unicode(&self) -> EscapeUnicode<'_> {
683        EscapeUnicode::new(self)
684    }
685
686    /// Represents iterators over the non-ASCII-whitespace non-empty substrings of this string.
687    #[must_use]
688    pub const fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> {
689        SplitAsciiWhitespace::new(self)
690    }
691
692    /// Represents iterators over the non-whitespace non-empty substrings of this string.
693    #[must_use]
694    pub const fn split_whitespace(&self) -> SplitWhitespace<'_> {
695        SplitWhitespace::new(self)
696    }
697
698    /// Returns the raw pointer to the underlying bytes of the string.
699    ///
700    /// The caller must ensure that the pointer is never written to.
701    #[must_use]
702    pub const fn as_ptr(&self) -> RawBytes {
703        self.as_str().as_ptr()
704    }
705
706    /// Returns the mutable pointer to the underlying bytes of the string.
707    ///
708    /// The caller must ensure that the string remains valid UTF-8.
709    pub const fn as_mut_ptr(&mut self) -> MutBytes {
710        self.as_mut_str().as_mut_ptr()
711    }
712
713    /// Checks that the provided index lies on the character boundary.
714    ///
715    /// The start and end of the string are considered to be boundaries.
716    ///
717    /// Returns [`false`] if the index is out of bounds.
718    #[must_use]
719    pub const fn is_char_boundary(&self, index: usize) -> bool {
720        self.as_str().is_char_boundary(index)
721    }
722
723    /// Splits the string into two at the given non-zero index.
724    ///
725    /// The index has to be non-zero in order to guarantee non-emptiness of the left string.
726    ///
727    /// # Panics
728    ///
729    /// Panics if the index is out of bounds or not on character boundary.
730    #[must_use]
731    pub const fn split_at(&self, index: Size) -> (&Self, &str) {
732        let (left, right) = self.as_str().split_at(index.get());
733
734        // SAFETY: splitting at non-zero index guarantees non-emptiness of the left string
735        let left_non_empty = unsafe { Self::from_str_unchecked(left) };
736
737        (left_non_empty, right)
738    }
739
740    /// Splits the mutable string into two at the given non-zero index.
741    ///
742    /// The index has to be non-zero in order to guarantee non-emptiness of the left string.
743    ///
744    /// # Panics
745    ///
746    /// Panics if the index is out of bounds or not on character boundary.
747    pub const fn split_at_mut(&mut self, index: Size) -> (&mut Self, &mut str) {
748        let (left, right) = self.as_mut_str().split_at_mut(index.get());
749
750        // SAFETY: splitting at non-zero index guarantees non-emptiness of the left string
751        let left_non_empty = unsafe { Self::from_mut_str_unchecked(left) };
752
753        (left_non_empty, right)
754    }
755
756    /// Splits the string into two at the given non-zero index, returning [`None`] if out of bounds
757    /// or not on character boundary.
758    ///
759    /// The index has to be non-zero in order to guarantee non-emptiness of the left string.
760    #[must_use]
761    pub const fn split_at_checked(&self, index: Size) -> Option<(&Self, &str)> {
762        let Some((left, right)) = self.as_str().split_at_checked(index.get()) else {
763            return None;
764        };
765
766        // SAFETY: splitting at non-zero index guarantees non-emptiness of the left string
767        let left_non_empty = unsafe { Self::from_str_unchecked(left) };
768
769        Some((left_non_empty, right))
770    }
771
772    /// Splits the mutable string into two at the given non-zero index,
773    /// returning [`None`] if out of bounds or not on character boundary.
774    ///
775    /// The index has to be non-zero in order to guarantee non-emptiness of the left string.
776    pub const fn split_at_mut_checked(&mut self, index: Size) -> Option<(&mut Self, &mut str)> {
777        let Some((left, right)) = self.as_mut_str().split_at_mut_checked(index.get()) else {
778            return None;
779        };
780
781        // SAFETY: splitting at non-zero index guarantees non-emptiness of the left string
782        let left_non_empty = unsafe { Self::from_mut_str_unchecked(left) };
783
784        Some((left_non_empty, right))
785    }
786
787    /// Parses this non-empty string into another type.
788    ///
789    /// [`parse_non_empty`] can be used with any type that implements the [`FromNonEmptyStr`] trait.
790    ///
791    /// # Errors
792    ///
793    /// Returns [`F::Error`] if parsing fails.
794    ///
795    /// [`parse_non_empty`]: Self::parse_non_empty
796    /// [`F::Error`]: FromNonEmptyStr::Error
797    pub fn parse_non_empty<F: FromNonEmptyStr>(&self) -> Result<F, F::Error> {
798        F::from_non_empty_str(self)
799    }
800
801    /// Returns non-empty iterators over the lines of this string.
802    #[must_use]
803    pub const fn lines(&self) -> Lines<'_> {
804        Lines::new(self)
805    }
806
807    /// Checks if all characters of the string are in the ASCII range.
808    #[must_use]
809    pub const fn is_ascii(&self) -> bool {
810        self.as_str().is_ascii()
811    }
812
813    /// Checks that the two strings are ASCII case-insensitively equal.
814    #[must_use]
815    pub const fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
816        self.as_str().eq_ignore_ascii_case(other.as_str())
817    }
818
819    /// Converts the string to its ASCII uppercase equivalent in-place.
820    pub const fn make_ascii_uppercase(&mut self) {
821        self.as_mut_str().make_ascii_uppercase();
822    }
823
824    /// Converts the string to its ASCII lowercase equivalent in-place.
825    pub const fn make_ascii_lowercase(&mut self) {
826        self.as_mut_str().make_ascii_lowercase();
827    }
828
829    /// Returns new string with leading ASCII whitespace removed.
830    #[must_use]
831    pub const fn trim_ascii_start(&self) -> &str {
832        self.as_str().trim_ascii_start()
833    }
834
835    /// Returns new string with trailing ASCII whitespace removed.
836    #[must_use]
837    pub const fn trim_ascii_end(&self) -> &str {
838        self.as_str().trim_ascii_end()
839    }
840
841    /// Returns new string with leading and trailing ASCII whitespace removed.
842    #[must_use]
843    pub const fn trim_ascii(&self) -> &str {
844        self.as_str().trim_ascii()
845    }
846}