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}