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}