1#[cfg(feature = "alloc")]
2use alloc::borrow::ToOwned;
3#[cfg(feature = "alloc")]
4use alloc::boxed::Box;
5use core::fmt;
6use core::ops::{Index, IndexMut};
7use core::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
8use core::slice::{self, Iter, IterMut, SliceIndex};
9#[cfg(feature = "std")]
10use std::error::Error;
11#[cfg(feature = "std")]
12use std::ffi::CStr;
13
14use ascii_char::AsciiChar;
15#[cfg(feature = "alloc")]
16use ascii_string::AsciiString;
17
18#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
25#[repr(transparent)]
26pub struct AsciiStr {
27 slice: [AsciiChar],
28}
29
30impl AsciiStr {
31 #[inline]
33 #[must_use]
34 pub fn as_str(&self) -> &str {
35 unsafe { &*(self as *const AsciiStr as *const str) }
37 }
38
39 #[inline]
41 #[must_use]
42 pub fn as_bytes(&self) -> &[u8] {
43 unsafe { &*(self as *const AsciiStr as *const [u8]) }
45 }
46
47 #[inline]
49 #[must_use]
50 pub const fn as_slice(&self) -> &[AsciiChar] {
51 &self.slice
52 }
53
54 #[inline]
56 #[must_use]
57 pub fn as_mut_slice(&mut self) -> &mut [AsciiChar] {
58 &mut self.slice
59 }
60
61 #[inline]
67 #[must_use]
68 pub const fn as_ptr(&self) -> *const AsciiChar {
69 self.as_slice().as_ptr()
70 }
71
72 #[inline]
78 #[must_use]
79 pub fn as_mut_ptr(&mut self) -> *mut AsciiChar {
80 self.as_mut_slice().as_mut_ptr()
81 }
82
83 #[cfg(feature = "alloc")]
85 #[must_use]
86 pub fn to_ascii_string(&self) -> AsciiString {
87 AsciiString::from(self.slice.to_vec())
88 }
89
90 #[inline]
104 pub fn from_ascii<B>(bytes: &B) -> Result<&AsciiStr, AsAsciiStrError>
105 where
106 B: AsRef<[u8]> + ?Sized,
107 {
108 bytes.as_ref().as_ascii_str()
109 }
110
111 #[inline]
125 #[must_use]
126 pub unsafe fn from_ascii_unchecked(bytes: &[u8]) -> &AsciiStr {
127 unsafe { bytes.as_ascii_str_unchecked() }
130 }
131
132 #[inline]
141 #[must_use]
142 pub const fn len(&self) -> usize {
143 self.slice.len()
144 }
145
146 #[inline]
157 #[must_use]
158 pub const fn is_empty(&self) -> bool {
159 self.len() == 0
160 }
161
162 #[inline]
164 #[must_use]
165 pub fn chars(&self) -> Chars {
166 Chars(self.slice.iter())
167 }
168
169 #[inline]
172 #[must_use]
173 pub fn chars_mut(&mut self) -> CharsMut {
174 CharsMut(self.slice.iter_mut())
175 }
176
177 #[must_use]
189 pub fn split(&self, on: AsciiChar) -> impl DoubleEndedIterator<Item = &AsciiStr> {
190 Split {
191 on,
192 ended: false,
193 chars: self.chars(),
194 }
195 }
196
197 #[inline]
203 #[must_use]
204 pub fn lines(&self) -> impl DoubleEndedIterator<Item = &AsciiStr> {
205 Lines { string: self }
206 }
207
208 #[must_use]
217 pub fn trim(&self) -> &Self {
218 self.trim_start().trim_end()
219 }
220
221 #[must_use]
230 pub fn trim_start(&self) -> &Self {
231 let whitespace_len = self
232 .chars()
233 .position(|ch| !ch.is_whitespace())
234 .unwrap_or_else(|| self.len());
235
236 unsafe { self.as_slice().get_unchecked(whitespace_len..).into() }
238 }
239
240 #[must_use]
249 pub fn trim_end(&self) -> &Self {
250 let whitespace_len = self
252 .chars()
253 .rev()
254 .position(|ch| !ch.is_whitespace())
255 .unwrap_or_else(|| self.len());
256
257 unsafe {
259 self.as_slice()
260 .get_unchecked(..self.len() - whitespace_len)
261 .into()
262 }
263 }
264
265 #[must_use]
267 pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
268 self.len() == other.len()
269 && self
270 .chars()
271 .zip(other.chars())
272 .all(|(ch, other_ch)| ch.eq_ignore_ascii_case(&other_ch))
273 }
274
275 pub fn make_ascii_uppercase(&mut self) {
277 for ch in self.chars_mut() {
278 *ch = ch.to_ascii_uppercase();
279 }
280 }
281
282 pub fn make_ascii_lowercase(&mut self) {
284 for ch in self.chars_mut() {
285 *ch = ch.to_ascii_lowercase();
286 }
287 }
288
289 #[cfg(feature = "alloc")]
291 #[must_use]
292 pub fn to_ascii_uppercase(&self) -> AsciiString {
293 let mut ascii_string = self.to_ascii_string();
294 ascii_string.make_ascii_uppercase();
295 ascii_string
296 }
297
298 #[cfg(feature = "alloc")]
300 #[must_use]
301 pub fn to_ascii_lowercase(&self) -> AsciiString {
302 let mut ascii_string = self.to_ascii_string();
303 ascii_string.make_ascii_lowercase();
304 ascii_string
305 }
306
307 #[inline]
309 #[must_use]
310 pub fn first(&self) -> Option<AsciiChar> {
311 self.slice.first().copied()
312 }
313
314 #[inline]
316 #[must_use]
317 pub fn last(&self) -> Option<AsciiChar> {
318 self.slice.last().copied()
319 }
320
321 #[cfg(feature = "alloc")]
323 #[inline]
324 #[must_use]
325 pub fn into_ascii_string(self: Box<Self>) -> AsciiString {
326 let slice = Box::<[AsciiChar]>::from(self);
327 AsciiString::from(slice.into_vec())
328 }
329}
330
331macro_rules! impl_partial_eq {
332 ($wider: ty) => {
333 impl PartialEq<$wider> for AsciiStr {
334 #[inline]
335 fn eq(&self, other: &$wider) -> bool {
336 <AsciiStr as AsRef<$wider>>::as_ref(self) == other
337 }
338 }
339 impl PartialEq<AsciiStr> for $wider {
340 #[inline]
341 fn eq(&self, other: &AsciiStr) -> bool {
342 self == <AsciiStr as AsRef<$wider>>::as_ref(other)
343 }
344 }
345 };
346}
347
348impl_partial_eq! {str}
349impl_partial_eq! {[u8]}
350impl_partial_eq! {[AsciiChar]}
351
352#[cfg(feature = "alloc")]
353impl ToOwned for AsciiStr {
354 type Owned = AsciiString;
355
356 #[inline]
357 fn to_owned(&self) -> AsciiString {
358 self.to_ascii_string()
359 }
360}
361
362impl AsRef<[u8]> for AsciiStr {
363 #[inline]
364 fn as_ref(&self) -> &[u8] {
365 self.as_bytes()
366 }
367}
368impl AsRef<str> for AsciiStr {
369 #[inline]
370 fn as_ref(&self) -> &str {
371 self.as_str()
372 }
373}
374impl AsRef<[AsciiChar]> for AsciiStr {
375 #[inline]
376 fn as_ref(&self) -> &[AsciiChar] {
377 &self.slice
378 }
379}
380impl AsMut<[AsciiChar]> for AsciiStr {
381 #[inline]
382 fn as_mut(&mut self) -> &mut [AsciiChar] {
383 &mut self.slice
384 }
385}
386
387impl Default for &'static AsciiStr {
388 #[inline]
389 fn default() -> &'static AsciiStr {
390 From::from(&[] as &[AsciiChar])
391 }
392}
393impl<'a> From<&'a [AsciiChar]> for &'a AsciiStr {
394 #[inline]
395 fn from(slice: &[AsciiChar]) -> &AsciiStr {
396 let ptr = slice as *const [AsciiChar] as *const AsciiStr;
397 unsafe { &*ptr }
398 }
399}
400impl<'a> From<&'a mut [AsciiChar]> for &'a mut AsciiStr {
401 #[inline]
402 fn from(slice: &mut [AsciiChar]) -> &mut AsciiStr {
403 let ptr = slice as *mut [AsciiChar] as *mut AsciiStr;
404 unsafe { &mut *ptr }
405 }
406}
407#[cfg(feature = "alloc")]
408impl From<Box<[AsciiChar]>> for Box<AsciiStr> {
409 #[inline]
410 fn from(owned: Box<[AsciiChar]>) -> Box<AsciiStr> {
411 let ptr = Box::into_raw(owned) as *mut AsciiStr;
412 unsafe { Box::from_raw(ptr) }
413 }
414}
415
416impl AsRef<AsciiStr> for AsciiStr {
417 #[inline]
418 fn as_ref(&self) -> &AsciiStr {
419 self
420 }
421}
422impl AsMut<AsciiStr> for AsciiStr {
423 #[inline]
424 fn as_mut(&mut self) -> &mut AsciiStr {
425 self
426 }
427}
428impl AsRef<AsciiStr> for [AsciiChar] {
429 #[inline]
430 fn as_ref(&self) -> &AsciiStr {
431 self.into()
432 }
433}
434impl AsMut<AsciiStr> for [AsciiChar] {
435 #[inline]
436 fn as_mut(&mut self) -> &mut AsciiStr {
437 self.into()
438 }
439}
440
441impl<'a> From<&'a AsciiStr> for &'a [AsciiChar] {
442 #[inline]
443 fn from(astr: &AsciiStr) -> &[AsciiChar] {
444 &astr.slice
445 }
446}
447impl<'a> From<&'a mut AsciiStr> for &'a mut [AsciiChar] {
448 #[inline]
449 fn from(astr: &mut AsciiStr) -> &mut [AsciiChar] {
450 &mut astr.slice
451 }
452}
453impl<'a> From<&'a AsciiStr> for &'a [u8] {
454 #[inline]
455 fn from(astr: &AsciiStr) -> &[u8] {
456 astr.as_bytes()
457 }
458}
459impl<'a> From<&'a AsciiStr> for &'a str {
460 #[inline]
461 fn from(astr: &AsciiStr) -> &str {
462 astr.as_str()
463 }
464}
465macro_rules! widen_box {
466 ($wider: ty) => {
467 #[cfg(feature = "alloc")]
468 impl From<Box<AsciiStr>> for Box<$wider> {
469 #[inline]
470 fn from(owned: Box<AsciiStr>) -> Box<$wider> {
471 let ptr = Box::into_raw(owned) as *mut $wider;
472 unsafe { Box::from_raw(ptr) }
473 }
474 }
475 };
476}
477widen_box! {[AsciiChar]}
478widen_box! {[u8]}
479widen_box! {str}
480
481impl AsRef<AsciiStr> for AsciiChar {
483 fn as_ref(&self) -> &AsciiStr {
484 slice::from_ref(self).into()
485 }
486}
487
488impl fmt::Display for AsciiStr {
489 #[inline]
490 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
491 fmt::Display::fmt(self.as_str(), f)
492 }
493}
494
495impl fmt::Debug for AsciiStr {
496 #[inline]
497 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
498 fmt::Debug::fmt(self.as_str(), f)
499 }
500}
501
502macro_rules! impl_index {
503 ($idx:ty) => {
504 #[allow(clippy::indexing_slicing)] impl Index<$idx> for AsciiStr {
506 type Output = AsciiStr;
507
508 #[inline]
509 fn index(&self, index: $idx) -> &AsciiStr {
510 self.slice[index].as_ref()
511 }
512 }
513
514 #[allow(clippy::indexing_slicing)] impl IndexMut<$idx> for AsciiStr {
516 #[inline]
517 fn index_mut(&mut self, index: $idx) -> &mut AsciiStr {
518 self.slice[index].as_mut()
519 }
520 }
521 };
522}
523
524impl_index! { Range<usize> }
525impl_index! { RangeTo<usize> }
526impl_index! { RangeFrom<usize> }
527impl_index! { RangeFull }
528impl_index! { RangeInclusive<usize> }
529impl_index! { RangeToInclusive<usize> }
530
531#[allow(clippy::indexing_slicing)] impl Index<usize> for AsciiStr {
533 type Output = AsciiChar;
534
535 #[inline]
536 fn index(&self, index: usize) -> &AsciiChar {
537 &self.slice[index]
538 }
539}
540
541#[allow(clippy::indexing_slicing)] impl IndexMut<usize> for AsciiStr {
543 #[inline]
544 fn index_mut(&mut self, index: usize) -> &mut AsciiChar {
545 &mut self.slice[index]
546 }
547}
548
549impl<'a> IntoIterator for &'a AsciiStr {
554 type Item = &'a AsciiChar;
555 type IntoIter = CharsRef<'a>;
556 #[inline]
557 fn into_iter(self) -> Self::IntoIter {
558 CharsRef(self.as_slice().iter())
559 }
560}
561
562impl<'a> IntoIterator for &'a mut AsciiStr {
563 type Item = &'a mut AsciiChar;
564 type IntoIter = CharsMut<'a>;
565 #[inline]
566 fn into_iter(self) -> Self::IntoIter {
567 self.chars_mut()
568 }
569}
570
571#[derive(Clone, Debug)]
573pub struct Chars<'a>(Iter<'a, AsciiChar>);
574impl<'a> Chars<'a> {
575 #[must_use]
577 pub fn as_str(&self) -> &'a AsciiStr {
578 self.0.as_slice().into()
579 }
580}
581impl<'a> Iterator for Chars<'a> {
582 type Item = AsciiChar;
583 #[inline]
584 fn next(&mut self) -> Option<AsciiChar> {
585 self.0.next().copied()
586 }
587 fn size_hint(&self) -> (usize, Option<usize>) {
588 self.0.size_hint()
589 }
590}
591impl<'a> DoubleEndedIterator for Chars<'a> {
592 #[inline]
593 fn next_back(&mut self) -> Option<AsciiChar> {
594 self.0.next_back().copied()
595 }
596}
597impl<'a> ExactSizeIterator for Chars<'a> {
598 fn len(&self) -> usize {
599 self.0.len()
600 }
601}
602
603#[derive(Debug)]
605pub struct CharsMut<'a>(IterMut<'a, AsciiChar>);
606impl<'a> CharsMut<'a> {
607 #[must_use]
609 pub fn into_str(self) -> &'a mut AsciiStr {
610 self.0.into_slice().into()
611 }
612}
613impl<'a> Iterator for CharsMut<'a> {
614 type Item = &'a mut AsciiChar;
615 #[inline]
616 fn next(&mut self) -> Option<&'a mut AsciiChar> {
617 self.0.next()
618 }
619 fn size_hint(&self) -> (usize, Option<usize>) {
620 self.0.size_hint()
621 }
622}
623impl<'a> DoubleEndedIterator for CharsMut<'a> {
624 #[inline]
625 fn next_back(&mut self) -> Option<&'a mut AsciiChar> {
626 self.0.next_back()
627 }
628}
629impl<'a> ExactSizeIterator for CharsMut<'a> {
630 fn len(&self) -> usize {
631 self.0.len()
632 }
633}
634
635#[derive(Clone, Debug)]
637pub struct CharsRef<'a>(Iter<'a, AsciiChar>);
638impl<'a> CharsRef<'a> {
639 #[must_use]
641 pub fn as_str(&self) -> &'a AsciiStr {
642 self.0.as_slice().into()
643 }
644}
645impl<'a> Iterator for CharsRef<'a> {
646 type Item = &'a AsciiChar;
647 #[inline]
648 fn next(&mut self) -> Option<&'a AsciiChar> {
649 self.0.next()
650 }
651 fn size_hint(&self) -> (usize, Option<usize>) {
652 self.0.size_hint()
653 }
654}
655impl<'a> DoubleEndedIterator for CharsRef<'a> {
656 #[inline]
657 fn next_back(&mut self) -> Option<&'a AsciiChar> {
658 self.0.next_back()
659 }
660}
661
662#[derive(Clone, Debug)]
666struct Split<'a> {
667 on: AsciiChar,
668 ended: bool,
669 chars: Chars<'a>,
670}
671impl<'a> Iterator for Split<'a> {
672 type Item = &'a AsciiStr;
673
674 fn next(&mut self) -> Option<&'a AsciiStr> {
675 if !self.ended {
676 let start: &AsciiStr = self.chars.as_str();
677 let split_on = self.on;
678
679 if let Some(at) = self.chars.position(|ch| ch == split_on) {
680 Some(unsafe { start.as_slice().get_unchecked(..at).into() })
682 } else {
683 self.ended = true;
684 Some(start)
685 }
686 } else {
687 None
688 }
689 }
690}
691impl<'a> DoubleEndedIterator for Split<'a> {
692 fn next_back(&mut self) -> Option<&'a AsciiStr> {
693 if !self.ended {
694 let start: &AsciiStr = self.chars.as_str();
695 let split_on = self.on;
696
697 if let Some(at) = self.chars.rposition(|ch| ch == split_on) {
698 Some(unsafe { start.as_slice().get_unchecked(at + 1..).into() })
700 } else {
701 self.ended = true;
702 Some(start)
703 }
704 } else {
705 None
706 }
707 }
708}
709
710#[derive(Clone, Debug)]
712struct Lines<'a> {
713 string: &'a AsciiStr,
714}
715impl<'a> Iterator for Lines<'a> {
716 type Item = &'a AsciiStr;
717
718 fn next(&mut self) -> Option<&'a AsciiStr> {
719 if let Some(idx) = self
720 .string
721 .chars()
722 .position(|chr| chr == AsciiChar::LineFeed)
723 {
724 let line = if idx > 0
726 && *unsafe { self.string.as_slice().get_unchecked(idx - 1) }
727 == AsciiChar::CarriageReturn
728 {
729 unsafe { self.string.as_slice().get_unchecked(..idx - 1).into() }
731 } else {
732 unsafe { self.string.as_slice().get_unchecked(..idx).into() }
734 };
735 self.string = unsafe { self.string.as_slice().get_unchecked(idx + 1..).into() };
737 Some(line)
738 } else if self.string.is_empty() {
739 None
740 } else {
741 let line = self.string;
742 self.string = unsafe { AsciiStr::from_ascii_unchecked(b"") };
744 Some(line)
745 }
746 }
747}
748
749impl<'a> DoubleEndedIterator for Lines<'a> {
750 fn next_back(&mut self) -> Option<&'a AsciiStr> {
751 if self.string.is_empty() {
752 return None;
753 }
754
755 if let Some(AsciiChar::LineFeed) = self.string.last() {
757 self.string = unsafe {
759 self.string
760 .as_slice()
761 .get_unchecked(..self.string.len() - 1)
762 .into()
763 };
764
765 if let Some(AsciiChar::CarriageReturn) = self.string.last() {
766 self.string = unsafe {
768 self.string
769 .as_slice()
770 .get_unchecked(..self.string.len() - 1)
771 .into()
772 };
773 }
774 }
775
776 let lf_rev_pos = self
778 .string
779 .chars()
780 .rev()
781 .position(|ch| ch == AsciiChar::LineFeed)
782 .unwrap_or_else(|| self.string.len());
783
784 let line = unsafe {
788 self.string
789 .as_slice()
790 .get_unchecked(self.string.len() - lf_rev_pos..)
791 .into()
792 };
793 self.string = unsafe {
794 self.string
795 .as_slice()
796 .get_unchecked(..self.string.len() - lf_rev_pos)
797 .into()
798 };
799 Some(line)
800 }
801}
802
803#[derive(Clone, Copy, PartialEq, Eq, Debug)]
807pub struct AsAsciiStrError(usize);
808
809const ERRORMSG_STR: &str = "one or more bytes are not ASCII";
810
811impl AsAsciiStrError {
812 #[inline]
816 #[must_use]
817 pub const fn valid_up_to(self) -> usize {
818 self.0
819 }
820 #[cfg(not(feature = "std"))]
821 #[inline]
823 #[must_use]
824 #[allow(clippy::unused_self)]
825 pub const fn description(&self) -> &'static str {
826 ERRORMSG_STR
827 }
828}
829impl fmt::Display for AsAsciiStrError {
830 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
831 write!(fmtr, "the byte at index {} is not ASCII", self.0)
832 }
833}
834#[cfg(feature = "std")]
835impl Error for AsAsciiStrError {
836 #[inline]
837 fn description(&self) -> &'static str {
838 ERRORMSG_STR
839 }
840}
841
842pub trait AsAsciiStr {
846 #[doc(hidden)]
848 type Inner;
849 fn slice_ascii<R>(&self, range: R) -> Result<&AsciiStr, AsAsciiStrError>
866 where
867 R: SliceIndex<[Self::Inner], Output = [Self::Inner]>;
868 fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
883 self.slice_ascii(..)
884 }
885 fn get_ascii(&self, index: usize) -> Option<AsciiChar> {
897 self.slice_ascii(index..=index)
898 .ok()
899 .and_then(AsciiStr::first)
900 }
901 unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr;
910}
911
912pub trait AsMutAsciiStr: AsAsciiStr {
914 fn slice_ascii_mut<R>(&mut self, range: R) -> Result<&mut AsciiStr, AsAsciiStrError>
920 where
921 R: SliceIndex<[Self::Inner], Output = [Self::Inner]>;
922
923 fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr, AsAsciiStrError> {
928 self.slice_ascii_mut(..)
929 }
930
931 unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr;
937}
938
939impl<'a, T> AsAsciiStr for &'a T
941where
942 T: AsAsciiStr + ?Sized,
943{
944 type Inner = <T as AsAsciiStr>::Inner;
945 fn slice_ascii<R>(&self, range: R) -> Result<&AsciiStr, AsAsciiStrError>
946 where
947 R: SliceIndex<[Self::Inner], Output = [Self::Inner]>,
948 {
949 <T as AsAsciiStr>::slice_ascii(*self, range)
950 }
951
952 unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
953 unsafe { <T as AsAsciiStr>::as_ascii_str_unchecked(*self) }
955 }
956}
957
958impl<'a, T> AsAsciiStr for &'a mut T
959where
960 T: AsAsciiStr + ?Sized,
961{
962 type Inner = <T as AsAsciiStr>::Inner;
963 fn slice_ascii<R>(&self, range: R) -> Result<&AsciiStr, AsAsciiStrError>
964 where
965 R: SliceIndex<[Self::Inner], Output = [Self::Inner]>,
966 {
967 <T as AsAsciiStr>::slice_ascii(*self, range)
968 }
969
970 unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
971 unsafe { <T as AsAsciiStr>::as_ascii_str_unchecked(*self) }
973 }
974}
975
976impl<'a, T> AsMutAsciiStr for &'a mut T
977where
978 T: AsMutAsciiStr + ?Sized,
979{
980 fn slice_ascii_mut<R>(&mut self, range: R) -> Result<&mut AsciiStr, AsAsciiStrError>
981 where
982 R: SliceIndex<[Self::Inner], Output = [Self::Inner]>,
983 {
984 <T as AsMutAsciiStr>::slice_ascii_mut(*self, range)
985 }
986
987 unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
988 unsafe { <T as AsMutAsciiStr>::as_mut_ascii_str_unchecked(*self) }
990 }
991}
992
993impl AsAsciiStr for AsciiStr {
994 type Inner = AsciiChar;
995
996 fn slice_ascii<R>(&self, range: R) -> Result<&AsciiStr, AsAsciiStrError>
997 where
998 R: SliceIndex<[AsciiChar], Output = [AsciiChar]>,
999 {
1000 self.slice.slice_ascii(range)
1001 }
1002
1003 #[inline]
1004 fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
1005 Ok(self)
1006 }
1007
1008 #[inline]
1009 unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
1010 self
1011 }
1012
1013 #[inline]
1014 fn get_ascii(&self, index: usize) -> Option<AsciiChar> {
1015 self.slice.get_ascii(index)
1016 }
1017}
1018impl AsMutAsciiStr for AsciiStr {
1019 fn slice_ascii_mut<R>(&mut self, range: R) -> Result<&mut AsciiStr, AsAsciiStrError>
1020 where
1021 R: SliceIndex<[AsciiChar], Output = [AsciiChar]>,
1022 {
1023 self.slice.slice_ascii_mut(range)
1024 }
1025
1026 #[inline]
1027 unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
1028 self
1029 }
1030}
1031
1032impl AsAsciiStr for [AsciiChar] {
1033 type Inner = AsciiChar;
1034 fn slice_ascii<R>(&self, range: R) -> Result<&AsciiStr, AsAsciiStrError>
1035 where
1036 R: SliceIndex<[AsciiChar], Output = [AsciiChar]>,
1037 {
1038 match self.get(range) {
1039 Some(slice) => Ok(slice.into()),
1040 None => Err(AsAsciiStrError(self.len())),
1041 }
1042 }
1043
1044 #[inline]
1045 fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
1046 Ok(self.into())
1047 }
1048
1049 #[inline]
1050 unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
1051 <&AsciiStr>::from(self)
1052 }
1053
1054 #[inline]
1055 fn get_ascii(&self, index: usize) -> Option<AsciiChar> {
1056 self.get(index).copied()
1057 }
1058}
1059impl AsMutAsciiStr for [AsciiChar] {
1060 fn slice_ascii_mut<R>(&mut self, range: R) -> Result<&mut AsciiStr, AsAsciiStrError>
1061 where
1062 R: SliceIndex<[AsciiChar], Output = [AsciiChar]>,
1063 {
1064 let len = self.len();
1065 match self.get_mut(range) {
1066 Some(slice) => Ok(slice.into()),
1067 None => Err(AsAsciiStrError(len)),
1068 }
1069 }
1070 #[inline]
1071 unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
1072 <&mut AsciiStr>::from(self)
1073 }
1074}
1075
1076impl AsAsciiStr for [u8] {
1077 type Inner = u8;
1078
1079 fn slice_ascii<R>(&self, range: R) -> Result<&AsciiStr, AsAsciiStrError>
1080 where
1081 R: SliceIndex<[u8], Output = [u8]>,
1082 {
1083 if let Some(slice) = self.get(range) {
1084 slice.as_ascii_str().map_err(|AsAsciiStrError(not_ascii)| {
1085 let offset = slice.as_ptr() as usize - self.as_ptr() as usize;
1086 AsAsciiStrError(offset + not_ascii)
1087 })
1088 } else {
1089 Err(AsAsciiStrError(self.len()))
1090 }
1091 }
1092
1093 fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
1094 if self.is_ascii() {
1096 unsafe { Ok(self.as_ascii_str_unchecked()) }
1098 } else {
1099 Err(AsAsciiStrError(
1100 self.iter().take_while(|&b| b.is_ascii()).count(),
1101 ))
1102 }
1103 }
1104
1105 #[inline]
1106 unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
1107 unsafe { &*(self as *const [u8] as *const AsciiStr) }
1109 }
1110}
1111impl AsMutAsciiStr for [u8] {
1112 fn slice_ascii_mut<R>(&mut self, range: R) -> Result<&mut AsciiStr, AsAsciiStrError>
1113 where
1114 R: SliceIndex<[u8], Output = [u8]>,
1115 {
1116 let (ptr, len) = (self.as_ptr(), self.len());
1117 if let Some(slice) = self.get_mut(range) {
1118 let slice_ptr = slice.as_ptr();
1119 slice
1120 .as_mut_ascii_str()
1121 .map_err(|AsAsciiStrError(not_ascii)| {
1122 let offset = slice_ptr as usize - ptr as usize;
1123 AsAsciiStrError(offset + not_ascii)
1124 })
1125 } else {
1126 Err(AsAsciiStrError(len))
1127 }
1128 }
1129
1130 fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr, AsAsciiStrError> {
1131 if self.is_ascii() {
1133 unsafe { Ok(self.as_mut_ascii_str_unchecked()) }
1135 } else {
1136 Err(AsAsciiStrError(
1137 self.iter().take_while(|&b| b.is_ascii()).count(),
1138 ))
1139 }
1140 }
1141
1142 #[inline]
1143 unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
1144 unsafe { &mut *(self as *mut [u8] as *mut AsciiStr) }
1146 }
1147}
1148
1149impl AsAsciiStr for str {
1150 type Inner = u8;
1151 fn slice_ascii<R>(&self, range: R) -> Result<&AsciiStr, AsAsciiStrError>
1152 where
1153 R: SliceIndex<[u8], Output = [u8]>,
1154 {
1155 self.as_bytes().slice_ascii(range)
1156 }
1157 fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
1158 self.as_bytes().as_ascii_str()
1159 }
1160 #[inline]
1161 unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
1162 unsafe { self.as_bytes().as_ascii_str_unchecked() }
1164 }
1165}
1166impl AsMutAsciiStr for str {
1167 fn slice_ascii_mut<R>(&mut self, range: R) -> Result<&mut AsciiStr, AsAsciiStrError>
1168 where
1169 R: SliceIndex<[u8], Output = [u8]>,
1170 {
1171 let bytes = unsafe { self.as_bytes_mut() };
1174 match bytes.get_mut(range) {
1175 Some(slice) if slice.is_ascii() => {
1177 let ptr = slice.as_mut_ptr().cast::<AsciiChar>();
1179 let len = slice.len();
1180
1181 unsafe {
1184 let slice = core::slice::from_raw_parts_mut(ptr, len);
1185 Ok(<&mut AsciiStr>::from(slice))
1186 }
1187 }
1188 Some(slice) => {
1189 let not_ascii_len = slice.iter().copied().take_while(u8::is_ascii).count();
1190 let offset = slice.as_ptr() as usize - self.as_ptr() as usize;
1191
1192 Err(AsAsciiStrError(offset + not_ascii_len))
1193 }
1194 None => Err(AsAsciiStrError(self.len())),
1195 }
1196 }
1197 fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr, AsAsciiStrError> {
1198 match self.bytes().position(|b| !b.is_ascii()) {
1199 Some(index) => Err(AsAsciiStrError(index)),
1200 None => unsafe { Ok(self.as_mut_ascii_str_unchecked()) },
1202 }
1203 }
1204 #[inline]
1205 unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
1206 &mut *(self as *mut str as *mut AsciiStr)
1208 }
1209}
1210
1211#[cfg(feature = "std")]
1213impl AsAsciiStr for CStr {
1214 type Inner = u8;
1215 fn slice_ascii<R>(&self, range: R) -> Result<&AsciiStr, AsAsciiStrError>
1216 where
1217 R: SliceIndex<[u8], Output = [u8]>,
1218 {
1219 self.to_bytes().slice_ascii(range)
1220 }
1221 #[inline]
1222 fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
1223 self.to_bytes().as_ascii_str()
1224 }
1225 #[inline]
1226 unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
1227 unsafe { self.to_bytes().as_ascii_str_unchecked() }
1229 }
1230}
1231
1232#[cfg(test)]
1233mod tests {
1234 use super::{AsAsciiStr, AsAsciiStrError, AsMutAsciiStr, AsciiStr};
1235 #[cfg(feature = "alloc")]
1236 use alloc::string::{String, ToString};
1237 #[cfg(feature = "alloc")]
1238 use alloc::vec::Vec;
1239 use AsciiChar;
1240
1241 #[test]
1244 fn generic_as_ascii_str() {
1245 fn generic<C: AsAsciiStr + ?Sized>(c: &C) -> Result<&AsciiStr, AsAsciiStrError> {
1247 c.as_ascii_str()
1248 }
1249
1250 let arr = [AsciiChar::A];
1251 let ascii_str = arr.as_ref().into();
1252 let mut mut_arr = arr; let mut_ascii_str = mut_arr.as_mut().into();
1254 let mut_arr_mut_ref: &mut [AsciiChar] = &mut [AsciiChar::A];
1255 let mut string_bytes = [b'A'];
1256 let string_mut = unsafe { core::str::from_utf8_unchecked_mut(&mut string_bytes) }; let string_mut_bytes: &mut [u8] = &mut [b'A'];
1258
1259 #[rustfmt::skip]
1262 let _ = [
1263 assert_eq!(generic::<str >("A" ), Ok(ascii_str)),
1264 assert_eq!(generic::<[u8] >(&b"A"[..] ), Ok(ascii_str)),
1265 assert_eq!(generic::<AsciiStr >(ascii_str ), Ok(ascii_str)),
1266 assert_eq!(generic::<[AsciiChar] >(&arr ), Ok(ascii_str)),
1267 assert_eq!(generic::<&str >(&"A" ), Ok(ascii_str)),
1268 assert_eq!(generic::<&[u8] >(&&b"A"[..] ), Ok(ascii_str)),
1269 assert_eq!(generic::<&AsciiStr >(&ascii_str ), Ok(ascii_str)),
1270 assert_eq!(generic::<&[AsciiChar] >(&&arr[..] ), Ok(ascii_str)),
1271 assert_eq!(generic::<&mut str >(&string_mut ), Ok(ascii_str)),
1272 assert_eq!(generic::<&mut [u8] >(&string_mut_bytes), Ok(ascii_str)),
1273 assert_eq!(generic::<&mut AsciiStr >(&mut_ascii_str ), Ok(ascii_str)),
1274 assert_eq!(generic::<&mut [AsciiChar]>(&mut_arr_mut_ref ), Ok(ascii_str)),
1275 ];
1276 }
1277
1278 #[cfg(feature = "std")]
1279 #[test]
1280 fn cstring_as_ascii_str() {
1281 use std::ffi::CString;
1282 fn generic<C: AsAsciiStr + ?Sized>(c: &C) -> Result<&AsciiStr, AsAsciiStrError> {
1283 c.as_ascii_str()
1284 }
1285 let arr = [AsciiChar::A];
1286 let ascii_str: &AsciiStr = arr.as_ref().into();
1287 let cstr = CString::new("A").unwrap();
1288 assert_eq!(generic(&*cstr), Ok(ascii_str));
1289 }
1290
1291 #[test]
1292 fn generic_as_mut_ascii_str() {
1293 fn generic_mut<C: AsMutAsciiStr + ?Sized>(
1294 c: &mut C,
1295 ) -> Result<&mut AsciiStr, AsAsciiStrError> {
1296 c.as_mut_ascii_str()
1297 }
1298
1299 let mut arr_mut = [AsciiChar::B];
1300 let mut ascii_str_mut: &mut AsciiStr = arr_mut.as_mut().into();
1301 let mut arr_mut_2 = [AsciiChar::B];
1303 let ascii_str_mut_2: &mut AsciiStr = arr_mut_2.as_mut().into();
1304 assert_eq!(generic_mut(&mut ascii_str_mut), Ok(&mut *ascii_str_mut_2));
1305 assert_eq!(generic_mut(ascii_str_mut), Ok(&mut *ascii_str_mut_2));
1306 }
1307
1308 #[test]
1309 fn as_ascii_str() {
1310 macro_rules! err {{$i:expr} => {Err(AsAsciiStrError($i))}}
1311 let s = "abčd";
1312 let b = s.as_bytes();
1313 assert_eq!(s.as_ascii_str(), err!(2));
1314 assert_eq!(b.as_ascii_str(), err!(2));
1315 let a: &AsciiStr = [AsciiChar::a, AsciiChar::b][..].as_ref();
1316 assert_eq!(s[..2].as_ascii_str(), Ok(a));
1317 assert_eq!(b[..2].as_ascii_str(), Ok(a));
1318 assert_eq!(s.slice_ascii(..2), Ok(a));
1319 assert_eq!(b.slice_ascii(..2), Ok(a));
1320 assert_eq!(s.slice_ascii(..=2), err!(2));
1321 assert_eq!(b.slice_ascii(..=2), err!(2));
1322 assert_eq!(s.get_ascii(4), Some(AsciiChar::d));
1323 assert_eq!(b.get_ascii(4), Some(AsciiChar::d));
1324 assert_eq!(s.get_ascii(3), None);
1325 assert_eq!(b.get_ascii(3), None);
1326 assert_eq!(s.get_ascii(b.len()), None);
1327 assert_eq!(b.get_ascii(b.len()), None);
1328 assert_eq!(a.get_ascii(0), Some(AsciiChar::a));
1329 assert_eq!(a.get_ascii(a.len()), None);
1330 }
1331
1332 #[test]
1333 #[cfg(feature = "std")]
1334 fn cstr_as_ascii_str() {
1335 use std::ffi::CStr;
1336 macro_rules! err {{$i:expr} => {Err(AsAsciiStrError($i))}}
1337 let cstr = CStr::from_bytes_with_nul(b"a\xbbcde\xffg\0").unwrap();
1338 assert_eq!(cstr.as_ascii_str(), err!(1));
1339 assert_eq!(cstr.slice_ascii(2..), err!(5));
1340 assert_eq!(cstr.get_ascii(5), None);
1341 assert_eq!(cstr.get_ascii(6), Some(AsciiChar::g));
1342 assert_eq!(cstr.get_ascii(7), None);
1343 let ascii_slice = &[AsciiChar::X, AsciiChar::Y, AsciiChar::Z, AsciiChar::Null][..];
1344 let ascii_str: &AsciiStr = ascii_slice.as_ref();
1345 let cstr = CStr::from_bytes_with_nul(ascii_str.as_bytes()).unwrap();
1346 assert_eq!(cstr.slice_ascii(..2), Ok(&ascii_str[..2]));
1347 assert_eq!(cstr.as_ascii_str(), Ok(&ascii_str[..3]));
1348 }
1349
1350 #[test]
1351 #[cfg(feature = "alloc")]
1352 fn as_mut_ascii_str() {
1353 macro_rules! err {{$i:expr} => {Err(AsAsciiStrError($i))}}
1354 let mut s: String = "abčd".to_string();
1355 let mut b: Vec<u8> = s.clone().into();
1356 let mut first = [AsciiChar::a, AsciiChar::b];
1357 let mut second = [AsciiChar::d];
1358 assert_eq!(s.as_mut_ascii_str(), err!(2));
1359 assert_eq!(b.as_mut_ascii_str(), err!(2));
1360 assert_eq!(s.slice_ascii_mut(..), err!(2));
1361 assert_eq!(b.slice_ascii_mut(..), err!(2));
1362 assert_eq!(s[..2].as_mut_ascii_str(), Ok((&mut first[..]).into()));
1363 assert_eq!(b[..2].as_mut_ascii_str(), Ok((&mut first[..]).into()));
1364 assert_eq!(s.slice_ascii_mut(0..2), Ok((&mut first[..]).into()));
1365 assert_eq!(b.slice_ascii_mut(0..2), Ok((&mut first[..]).into()));
1366 assert_eq!(s.slice_ascii_mut(4..), Ok((&mut second[..]).into()));
1367 assert_eq!(b.slice_ascii_mut(4..), Ok((&mut second[..]).into()));
1368 assert_eq!(s.slice_ascii_mut(4..=10), err!(5));
1369 assert_eq!(b.slice_ascii_mut(4..=10), err!(5));
1370 }
1371
1372 #[test]
1373 fn default() {
1374 let default: &'static AsciiStr = Default::default();
1375 assert!(default.is_empty());
1376 }
1377
1378 #[test]
1379 #[allow(clippy::redundant_slicing)]
1380 fn index() {
1381 let mut arr = [AsciiChar::A, AsciiChar::B, AsciiChar::C, AsciiChar::D];
1382 {
1383 let a: &AsciiStr = arr[..].into();
1384 assert_eq!(a[..].as_slice(), &a.as_slice()[..]);
1385 assert_eq!(a[..4].as_slice(), &a.as_slice()[..4]);
1386 assert_eq!(a[4..].as_slice(), &a.as_slice()[4..]);
1387 assert_eq!(a[2..3].as_slice(), &a.as_slice()[2..3]);
1388 assert_eq!(a[..=3].as_slice(), &a.as_slice()[..=3]);
1389 assert_eq!(a[1..=1].as_slice(), &a.as_slice()[1..=1]);
1390 }
1391 let mut copy = arr;
1392 let a_mut: &mut AsciiStr = { &mut arr[..] }.into();
1393 assert_eq!(a_mut[..].as_mut_slice(), &mut copy[..]);
1394 assert_eq!(a_mut[..2].as_mut_slice(), &mut copy[..2]);
1395 assert_eq!(a_mut[3..].as_mut_slice(), &mut copy[3..]);
1396 assert_eq!(a_mut[4..4].as_mut_slice(), &mut copy[4..4]);
1397 assert_eq!(a_mut[..=0].as_mut_slice(), &mut copy[..=0]);
1398 assert_eq!(a_mut[0..=2].as_mut_slice(), &mut copy[0..=2]);
1399 }
1400
1401 #[test]
1402 fn as_str() {
1403 let b = b"( ;";
1404 let v = AsciiStr::from_ascii(b).unwrap();
1405 assert_eq!(v.as_str(), "( ;");
1406 assert_eq!(AsRef::<str>::as_ref(v), "( ;");
1407 }
1408
1409 #[test]
1410 fn as_bytes() {
1411 let b = b"( ;";
1412 let v = AsciiStr::from_ascii(b).unwrap();
1413 assert_eq!(v.as_bytes(), b"( ;");
1414 assert_eq!(AsRef::<[u8]>::as_ref(v), b"( ;");
1415 }
1416
1417 #[test]
1418 fn make_ascii_case() {
1419 let mut bytes = ([b'a', b'@', b'A'], [b'A', b'@', b'a']);
1420 let a = bytes.0.as_mut_ascii_str().unwrap();
1421 let b = bytes.1.as_mut_ascii_str().unwrap();
1422 assert!(a.eq_ignore_ascii_case(b));
1423 assert!(b.eq_ignore_ascii_case(a));
1424 a.make_ascii_lowercase();
1425 b.make_ascii_uppercase();
1426 assert_eq!(a, "a@a");
1427 assert_eq!(b, "A@A");
1428 }
1429
1430 #[test]
1431 #[cfg(feature = "alloc")]
1432 fn to_ascii_case() {
1433 let bytes = ([b'a', b'@', b'A'], [b'A', b'@', b'a']);
1434 let a = bytes.0.as_ascii_str().unwrap();
1435 let b = bytes.1.as_ascii_str().unwrap();
1436 assert_eq!(a.to_ascii_lowercase().as_str(), "a@a");
1437 assert_eq!(a.to_ascii_uppercase().as_str(), "A@A");
1438 assert_eq!(b.to_ascii_lowercase().as_str(), "a@a");
1439 assert_eq!(b.to_ascii_uppercase().as_str(), "A@A");
1440 }
1441
1442 #[test]
1443 fn chars_iter() {
1444 let chars = &[
1445 b'h', b'e', b'l', b'l', b'o', b' ', b'w', b'o', b'r', b'l', b'd', b'\0',
1446 ];
1447 let ascii = AsciiStr::from_ascii(chars).unwrap();
1448 for (achar, byte) in ascii.chars().zip(chars.iter().copied()) {
1449 assert_eq!(achar, byte);
1450 }
1451 }
1452
1453 #[test]
1454 fn chars_iter_mut() {
1455 let chars = &mut [
1456 b'h', b'e', b'l', b'l', b'o', b' ', b'w', b'o', b'r', b'l', b'd', b'\0',
1457 ];
1458 let ascii = chars.as_mut_ascii_str().unwrap();
1459 *ascii.chars_mut().next().unwrap() = AsciiChar::H;
1460 assert_eq!(ascii[0], b'H');
1461 }
1462
1463 #[test]
1464 fn lines_iter() {
1465 use core::iter::Iterator;
1466
1467 let lines: [&str; 4] = ["foo", "bar", "", "baz"];
1468 let joined = "foo\r\nbar\n\nbaz\n";
1469 let ascii = AsciiStr::from_ascii(joined.as_bytes()).unwrap();
1470 for (asciiline, line) in ascii.lines().zip(&lines) {
1471 assert_eq!(asciiline, *line);
1472 }
1473 assert_eq!(ascii.lines().count(), lines.len());
1474
1475 let lines: [&str; 4] = ["foo", "bar", "", "baz"];
1476 let joined = "foo\r\nbar\n\nbaz";
1477 let ascii = AsciiStr::from_ascii(joined.as_bytes()).unwrap();
1478 for (asciiline, line) in ascii.lines().zip(&lines) {
1479 assert_eq!(asciiline, *line);
1480 }
1481 assert_eq!(ascii.lines().count(), lines.len());
1482
1483 let trailing_line_break = b"\n";
1484 let ascii = AsciiStr::from_ascii(&trailing_line_break).unwrap();
1485 let mut line_iter = ascii.lines();
1486 assert_eq!(line_iter.next(), Some(AsciiStr::from_ascii("").unwrap()));
1487 assert_eq!(line_iter.next(), None);
1488
1489 let empty_lines = b"\n\r\n\n\r\n";
1490 let mut iter_count = 0;
1491 let ascii = AsciiStr::from_ascii(&empty_lines).unwrap();
1492 for line in ascii.lines() {
1493 iter_count += 1;
1494 assert!(line.is_empty());
1495 }
1496 assert_eq!(4, iter_count);
1497 }
1498
1499 #[test]
1500 fn lines_iter_rev() {
1501 let joined = "foo\r\nbar\n\nbaz\n";
1502 let ascii = AsciiStr::from_ascii(joined.as_bytes()).unwrap();
1503 assert_eq!(ascii.lines().rev().count(), 4);
1504 assert_eq!(ascii.lines().rev().count(), joined.lines().rev().count());
1505 for (asciiline, line) in ascii.lines().rev().zip(joined.lines().rev()) {
1506 assert_eq!(asciiline, line);
1507 }
1508 let mut iter = ascii.lines();
1509 assert_eq!(iter.next(), Some("foo".as_ascii_str().unwrap()));
1510 assert_eq!(iter.next_back(), Some("baz".as_ascii_str().unwrap()));
1511 assert_eq!(iter.next_back(), Some("".as_ascii_str().unwrap()));
1512 assert_eq!(iter.next(), Some("bar".as_ascii_str().unwrap()));
1513
1514 let empty_lines = b"\n\r\n\n\r\n";
1515 let mut iter_count = 0;
1516 let ascii = AsciiStr::from_ascii(&empty_lines).unwrap();
1517 for line in ascii.lines().rev() {
1518 iter_count += 1;
1519 assert!(line.is_empty());
1520 }
1521 assert_eq!(4, iter_count);
1522 }
1523
1524 #[test]
1525 fn lines_iter_empty() {
1526 assert_eq!("".as_ascii_str().unwrap().lines().next(), None);
1527 assert_eq!("".as_ascii_str().unwrap().lines().next_back(), None);
1528 assert_eq!("".lines().next(), None);
1529 }
1530
1531 #[test]
1532 fn split_str() {
1533 fn split_equals_str(haystack: &str, needle: char) {
1534 let mut strs = haystack.split(needle);
1535 let mut asciis = haystack
1536 .as_ascii_str()
1537 .unwrap()
1538 .split(AsciiChar::from_ascii(needle).unwrap())
1539 .map(AsciiStr::as_str);
1540 loop {
1541 assert_eq!(asciis.size_hint(), strs.size_hint());
1542 let (a, s) = (asciis.next(), strs.next());
1543 assert_eq!(a, s);
1544 if a == None {
1545 break;
1546 }
1547 }
1548 if strs.next() == None {
1550 assert_eq!(asciis.next(), None);
1551 }
1552 }
1553 split_equals_str("", '=');
1554 split_equals_str("1,2,3", ',');
1555 split_equals_str("foo;bar;baz;", ';');
1556 split_equals_str("|||", '|');
1557 split_equals_str(" a b c ", ' ');
1558 }
1559
1560 #[test]
1561 fn split_str_rev() {
1562 let words = " foo bar baz ";
1563 let ascii = words.as_ascii_str().unwrap();
1564 for (word, asciiword) in words
1565 .split(' ')
1566 .rev()
1567 .zip(ascii.split(AsciiChar::Space).rev())
1568 {
1569 assert_eq!(asciiword, word);
1570 }
1571 let mut iter = ascii.split(AsciiChar::Space);
1572 assert_eq!(iter.next(), Some("".as_ascii_str().unwrap()));
1573 assert_eq!(iter.next_back(), Some("".as_ascii_str().unwrap()));
1574 assert_eq!(iter.next(), Some("foo".as_ascii_str().unwrap()));
1575 assert_eq!(iter.next_back(), Some("baz".as_ascii_str().unwrap()));
1576 assert_eq!(iter.next_back(), Some("bar".as_ascii_str().unwrap()));
1577 assert_eq!(iter.next(), Some("".as_ascii_str().unwrap()));
1578 assert_eq!(iter.next_back(), None);
1579 }
1580
1581 #[test]
1582 fn split_str_empty() {
1583 let empty = <&AsciiStr>::default();
1584 let mut iter = empty.split(AsciiChar::NAK);
1585 assert_eq!(iter.next(), Some(empty));
1586 assert_eq!(iter.next(), None);
1587 let mut iter = empty.split(AsciiChar::NAK);
1588 assert_eq!(iter.next_back(), Some(empty));
1589 assert_eq!(iter.next_back(), None);
1590 assert_eq!("".split('s').next(), Some("")); }
1592
1593 #[test]
1594 #[cfg(feature = "std")]
1595 fn fmt_ascii_str() {
1596 let s = "abc".as_ascii_str().unwrap();
1597 assert_eq!(format!("{}", s), "abc".to_string());
1598 assert_eq!(format!("{:?}", s), "\"abc\"".to_string());
1599 }
1600}