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