non_empty_str/
str.rs

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