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}