1use alloc::borrow::{Borrow, BorrowMut, Cow, ToOwned};
2use alloc::fmt;
3use alloc::string::String;
4use alloc::vec::Vec;
5use alloc::boxed::Box;
6use alloc::rc::Rc;
7use alloc::sync::Arc;
8#[cfg(feature = "std")]
9use core::any::Any;
10use core::iter::FromIterator;
11use core::mem;
12use core::ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut};
13use core::str::FromStr;
14#[cfg(feature = "std")]
15use std::error::Error;
16#[cfg(feature = "std")]
17use std::ffi::{CStr, CString};
18
19use ascii_char::AsciiChar;
20use ascii_str::{AsAsciiStr, AsAsciiStrError, AsciiStr};
21
22#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[repr(transparent)]
25pub struct AsciiString {
26 vec: Vec<AsciiChar>,
27}
28
29impl AsciiString {
30 #[inline]
38 #[must_use]
39 pub const fn new() -> Self {
40 AsciiString { vec: Vec::new() }
41 }
42
43 #[inline]
53 #[must_use]
54 pub fn with_capacity(capacity: usize) -> Self {
55 AsciiString {
56 vec: Vec::with_capacity(capacity),
57 }
58 }
59
60 #[inline]
98 #[must_use]
99 pub unsafe fn from_raw_parts(buf: *mut AsciiChar, length: usize, capacity: usize) -> Self {
100 AsciiString {
101 vec: unsafe { Vec::from_raw_parts(buf, length, capacity) },
105 }
106 }
107
108 #[inline]
116 #[must_use]
117 pub unsafe fn from_ascii_unchecked<B>(bytes: B) -> Self
118 where
119 B: Into<Vec<u8>>,
120 {
121 let mut bytes = bytes.into();
122 let ptr = bytes.as_mut_ptr().cast::<AsciiChar>();
124 let length = bytes.len();
125 let capacity = bytes.capacity();
126 mem::forget(bytes);
127
128 let vec = Vec::from_raw_parts(ptr, length, capacity);
133
134 Self { vec }
135 }
136
137 pub fn from_ascii<B>(bytes: B) -> Result<AsciiString, FromAsciiError<B>>
151 where
152 B: Into<Vec<u8>> + AsRef<[u8]>,
153 {
154 match bytes.as_ref().as_ascii_str() {
155 Ok(_) => Ok(unsafe { AsciiString::from_ascii_unchecked(bytes) }),
157 Err(e) => Err(FromAsciiError {
158 error: e,
159 owner: bytes,
160 }),
161 }
162 }
163
164 #[inline]
175 pub fn push_str(&mut self, string: &AsciiStr) {
176 self.vec.extend(string.chars());
177 }
178
179 #[inline]
193 pub fn insert_str(&mut self, idx: usize, string: &AsciiStr) {
194 self.vec.reserve(string.len());
195 self.vec.splice(idx..idx, string.into_iter().copied());
196 }
197
198 #[inline]
207 #[must_use]
208 pub fn capacity(&self) -> usize {
209 self.vec.capacity()
210 }
211
212 #[inline]
226 pub fn reserve(&mut self, additional: usize) {
227 self.vec.reserve(additional);
228 }
229
230 #[inline]
248
249 pub fn reserve_exact(&mut self, additional: usize) {
250 self.vec.reserve_exact(additional);
251 }
252
253 #[inline]
266
267 pub fn shrink_to_fit(&mut self) {
268 self.vec.shrink_to_fit();
269 }
270
271 #[inline]
283
284 pub fn push(&mut self, ch: AsciiChar) {
285 self.vec.push(ch);
286 }
287
288 #[inline]
301
302 pub fn truncate(&mut self, new_len: usize) {
303 self.vec.truncate(new_len);
304 }
305
306 #[inline]
319 #[must_use]
320 pub fn pop(&mut self) -> Option<AsciiChar> {
321 self.vec.pop()
322 }
323
324 #[inline]
341 #[must_use]
342 pub fn remove(&mut self, idx: usize) -> AsciiChar {
343 self.vec.remove(idx)
344 }
345
346 #[inline]
362
363 pub fn insert(&mut self, idx: usize, ch: AsciiChar) {
364 self.vec.insert(idx, ch);
365 }
366
367 #[inline]
376 #[must_use]
377 pub fn len(&self) -> usize {
378 self.vec.len()
379 }
380
381 #[inline]
392 #[must_use]
393 pub fn is_empty(&self) -> bool {
394 self.len() == 0
395 }
396
397 #[inline]
407
408 pub fn clear(&mut self) {
409 self.vec.clear();
410 }
411
412 #[inline]
416 #[must_use]
417 pub fn into_boxed_ascii_str(self) -> Box<AsciiStr> {
418 let slice = self.vec.into_boxed_slice();
419 Box::from(slice)
420 }
421}
422
423impl Deref for AsciiString {
424 type Target = AsciiStr;
425
426 #[inline]
427 fn deref(&self) -> &AsciiStr {
428 self.vec.as_slice().as_ref()
429 }
430}
431
432impl DerefMut for AsciiString {
433 #[inline]
434 fn deref_mut(&mut self) -> &mut AsciiStr {
435 self.vec.as_mut_slice().as_mut()
436 }
437}
438
439impl PartialEq<str> for AsciiString {
440 #[inline]
441 fn eq(&self, other: &str) -> bool {
442 **self == *other
443 }
444}
445
446impl PartialEq<AsciiString> for str {
447 #[inline]
448 fn eq(&self, other: &AsciiString) -> bool {
449 **other == *self
450 }
451}
452
453macro_rules! impl_eq {
454 ($lhs:ty, $rhs:ty) => {
455 impl PartialEq<$rhs> for $lhs {
456 #[inline]
457 fn eq(&self, other: &$rhs) -> bool {
458 PartialEq::eq(&**self, &**other)
459 }
460 }
461 };
462}
463
464impl_eq! { AsciiString, String }
465impl_eq! { String, AsciiString }
466impl_eq! { &AsciiStr, String }
467impl_eq! { String, &AsciiStr }
468impl_eq! { &AsciiStr, AsciiString }
469impl_eq! { AsciiString, &AsciiStr }
470impl_eq! { &str, AsciiString }
471impl_eq! { AsciiString, &str }
472
473impl Borrow<AsciiStr> for AsciiString {
474 #[inline]
475 fn borrow(&self) -> &AsciiStr {
476 &**self
477 }
478}
479
480impl BorrowMut<AsciiStr> for AsciiString {
481 #[inline]
482 fn borrow_mut(&mut self) -> &mut AsciiStr {
483 &mut **self
484 }
485}
486
487impl From<Vec<AsciiChar>> for AsciiString {
488 #[inline]
489 fn from(vec: Vec<AsciiChar>) -> Self {
490 AsciiString { vec }
491 }
492}
493
494impl From<AsciiChar> for AsciiString {
495 #[inline]
496 fn from(ch: AsciiChar) -> Self {
497 AsciiString { vec: vec![ch] }
498 }
499}
500
501impl From<AsciiString> for Vec<u8> {
502 fn from(mut s: AsciiString) -> Vec<u8> {
503 let ptr = s.vec.as_mut_ptr().cast::<u8>();
506 let length = s.vec.len();
507 let capacity = s.vec.capacity();
508 mem::forget(s);
509
510 unsafe { Vec::from_raw_parts(ptr, length, capacity) }
514 }
515}
516
517impl From<AsciiString> for Vec<AsciiChar> {
518 fn from(s: AsciiString) -> Vec<AsciiChar> {
519 s.vec
520 }
521}
522
523impl<'a> From<&'a AsciiStr> for AsciiString {
524 #[inline]
525 fn from(s: &'a AsciiStr) -> Self {
526 s.to_ascii_string()
527 }
528}
529
530impl<'a> From<&'a [AsciiChar]> for AsciiString {
531 #[inline]
532 fn from(s: &'a [AsciiChar]) -> AsciiString {
533 s.iter().copied().collect()
534 }
535}
536
537impl From<AsciiString> for String {
538 #[inline]
539 fn from(s: AsciiString) -> String {
540 unsafe { String::from_utf8_unchecked(s.into()) }
542 }
543}
544
545impl From<Box<AsciiStr>> for AsciiString {
546 #[inline]
547 fn from(boxed: Box<AsciiStr>) -> Self {
548 boxed.into_ascii_string()
549 }
550}
551
552impl From<AsciiString> for Box<AsciiStr> {
553 #[inline]
554 fn from(string: AsciiString) -> Self {
555 string.into_boxed_ascii_str()
556 }
557}
558
559impl From<AsciiString> for Rc<AsciiStr> {
560 fn from(s: AsciiString) -> Rc<AsciiStr> {
561 let var: Rc<[AsciiChar]> = s.vec.into();
562 unsafe { Rc::from_raw(Rc::into_raw(var) as *const AsciiStr) }
564 }
565}
566
567impl From<AsciiString> for Arc<AsciiStr> {
568 fn from(s: AsciiString) -> Arc<AsciiStr> {
569 let var: Arc<[AsciiChar]> = s.vec.into();
570 unsafe { Arc::from_raw(Arc::into_raw(var) as *const AsciiStr) }
572 }
573}
574
575impl<'a> From<Cow<'a, AsciiStr>> for AsciiString {
576 fn from(cow: Cow<'a, AsciiStr>) -> AsciiString {
577 cow.into_owned()
578 }
579}
580
581impl From<AsciiString> for Cow<'static, AsciiStr> {
582 fn from(string: AsciiString) -> Cow<'static, AsciiStr> {
583 Cow::Owned(string)
584 }
585}
586
587impl<'a> From<&'a AsciiStr> for Cow<'a, AsciiStr> {
588 fn from(s: &'a AsciiStr) -> Cow<'a, AsciiStr> {
589 Cow::Borrowed(s)
590 }
591}
592
593impl AsRef<AsciiStr> for AsciiString {
594 #[inline]
595 fn as_ref(&self) -> &AsciiStr {
596 &**self
597 }
598}
599
600impl AsRef<[AsciiChar]> for AsciiString {
601 #[inline]
602 fn as_ref(&self) -> &[AsciiChar] {
603 &self.vec
604 }
605}
606
607impl AsRef<[u8]> for AsciiString {
608 #[inline]
609 fn as_ref(&self) -> &[u8] {
610 self.as_bytes()
611 }
612}
613
614impl AsRef<str> for AsciiString {
615 #[inline]
616 fn as_ref(&self) -> &str {
617 self.as_str()
618 }
619}
620
621impl AsMut<AsciiStr> for AsciiString {
622 #[inline]
623 fn as_mut(&mut self) -> &mut AsciiStr {
624 &mut *self
625 }
626}
627
628impl AsMut<[AsciiChar]> for AsciiString {
629 #[inline]
630 fn as_mut(&mut self) -> &mut [AsciiChar] {
631 &mut self.vec
632 }
633}
634
635impl FromStr for AsciiString {
636 type Err = AsAsciiStrError;
637
638 fn from_str(s: &str) -> Result<AsciiString, AsAsciiStrError> {
639 s.as_ascii_str().map(AsciiStr::to_ascii_string)
640 }
641}
642
643impl fmt::Display for AsciiString {
644 #[inline]
645 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
646 fmt::Display::fmt(&**self, f)
647 }
648}
649
650impl fmt::Debug for AsciiString {
651 #[inline]
652 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
653 fmt::Debug::fmt(&**self, f)
654 }
655}
656
657impl fmt::Write for AsciiString {
660 fn write_str(&mut self, s: &str) -> fmt::Result {
661 if let Ok(astr) = AsciiStr::from_ascii(s) {
662 self.push_str(astr);
663 Ok(())
664 } else {
665 Err(fmt::Error)
666 }
667 }
668
669 fn write_char(&mut self, c: char) -> fmt::Result {
670 if let Ok(achar) = AsciiChar::from_ascii(c) {
671 self.push(achar);
672 Ok(())
673 } else {
674 Err(fmt::Error)
675 }
676 }
677}
678
679impl<A: AsRef<AsciiStr>> FromIterator<A> for AsciiString {
680 fn from_iter<I: IntoIterator<Item = A>>(iter: I) -> AsciiString {
681 let mut buf = AsciiString::new();
682 buf.extend(iter);
683 buf
684 }
685}
686
687impl<A: AsRef<AsciiStr>> Extend<A> for AsciiString {
688 fn extend<I: IntoIterator<Item = A>>(&mut self, iterable: I) {
689 let iterator = iterable.into_iter();
690 let (lower_bound, _) = iterator.size_hint();
691 self.reserve(lower_bound);
692 for item in iterator {
693 self.push_str(item.as_ref());
694 }
695 }
696}
697
698impl<'a> Add<&'a AsciiStr> for AsciiString {
699 type Output = AsciiString;
700
701 #[inline]
702 fn add(mut self, other: &AsciiStr) -> AsciiString {
703 self.push_str(other);
704 self
705 }
706}
707
708impl<'a> AddAssign<&'a AsciiStr> for AsciiString {
709 #[inline]
710 fn add_assign(&mut self, other: &AsciiStr) {
711 self.push_str(other);
712 }
713}
714
715#[allow(clippy::indexing_slicing)] impl<T> Index<T> for AsciiString
717where
718 AsciiStr: Index<T>,
719{
720 type Output = <AsciiStr as Index<T>>::Output;
721
722 #[inline]
723 fn index(&self, index: T) -> &<AsciiStr as Index<T>>::Output {
724 &(**self)[index]
725 }
726}
727
728#[allow(clippy::indexing_slicing)] impl<T> IndexMut<T> for AsciiString
730where
731 AsciiStr: IndexMut<T>,
732{
733 #[inline]
734 fn index_mut(&mut self, index: T) -> &mut <AsciiStr as Index<T>>::Output {
735 &mut (**self)[index]
736 }
737}
738
739#[derive(Clone, Copy, PartialEq, Eq)]
754pub struct FromAsciiError<O> {
755 error: AsAsciiStrError,
756 owner: O,
757}
758impl<O> FromAsciiError<O> {
759 #[inline]
761 #[must_use]
762 pub fn ascii_error(&self) -> AsAsciiStrError {
763 self.error
764 }
765 #[inline]
767 #[must_use]
768 pub fn into_source(self) -> O {
769 self.owner
770 }
771}
772impl<O> fmt::Debug for FromAsciiError<O> {
773 #[inline]
774 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
775 fmt::Debug::fmt(&self.error, fmtr)
776 }
777}
778impl<O> fmt::Display for FromAsciiError<O> {
779 #[inline]
780 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
781 fmt::Display::fmt(&self.error, fmtr)
782 }
783}
784#[cfg(feature = "std")]
785impl<O: Any> Error for FromAsciiError<O> {
786 #[inline]
787 #[allow(deprecated)] fn description(&self) -> &str {
789 self.error.description()
790 }
791 fn cause(&self) -> Option<&dyn Error> {
793 Some(&self.error as &dyn Error)
794 }
795}
796
797pub trait IntoAsciiString: Sized {
799 unsafe fn into_ascii_string_unchecked(self) -> AsciiString;
805
806 fn into_ascii_string(self) -> Result<AsciiString, FromAsciiError<Self>>;
811}
812
813impl IntoAsciiString for Vec<AsciiChar> {
814 #[inline]
815 unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
816 AsciiString::from(self)
817 }
818 #[inline]
819 fn into_ascii_string(self) -> Result<AsciiString, FromAsciiError<Self>> {
820 Ok(AsciiString::from(self))
821 }
822}
823
824impl<'a> IntoAsciiString for &'a [AsciiChar] {
825 #[inline]
826 unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
827 AsciiString::from(self)
828 }
829 #[inline]
830 fn into_ascii_string(self) -> Result<AsciiString, FromAsciiError<Self>> {
831 Ok(AsciiString::from(self))
832 }
833}
834
835impl<'a> IntoAsciiString for &'a AsciiStr {
836 #[inline]
837 unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
838 AsciiString::from(self)
839 }
840 #[inline]
841 fn into_ascii_string(self) -> Result<AsciiString, FromAsciiError<Self>> {
842 Ok(AsciiString::from(self))
843 }
844}
845
846macro_rules! impl_into_ascii_string {
847 ('a, $wider:ty) => {
848 impl<'a> IntoAsciiString for $wider {
849 #[inline]
850 unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
851 unsafe { AsciiString::from_ascii_unchecked(self) }
853 }
854
855 #[inline]
856 fn into_ascii_string(self) -> Result<AsciiString, FromAsciiError<Self>> {
857 AsciiString::from_ascii(self)
858 }
859 }
860 };
861
862 ($wider:ty) => {
863 impl IntoAsciiString for $wider {
864 #[inline]
865 unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
866 unsafe { AsciiString::from_ascii_unchecked(self) }
868 }
869
870 #[inline]
871 fn into_ascii_string(self) -> Result<AsciiString, FromAsciiError<Self>> {
872 AsciiString::from_ascii(self)
873 }
874 }
875 };
876}
877
878impl_into_ascii_string! {AsciiString}
879impl_into_ascii_string! {Vec<u8>}
880impl_into_ascii_string! {'a, &'a [u8]}
881impl_into_ascii_string! {String}
882impl_into_ascii_string! {'a, &'a str}
883
884#[cfg(feature = "std")]
887impl IntoAsciiString for CString {
888 #[inline]
889 unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
890 unsafe { AsciiString::from_ascii_unchecked(self.into_bytes()) }
892 }
893
894 fn into_ascii_string(self) -> Result<AsciiString, FromAsciiError<Self>> {
895 AsciiString::from_ascii(self.into_bytes_with_nul())
896 .map_err(|FromAsciiError { error, owner }| {
897 FromAsciiError {
898 owner: unsafe { CString::from_vec_unchecked(owner) },
901 error,
902 }
903 })
904 .map(|mut s| {
905 let nul = s.pop();
906 debug_assert_eq!(nul, Some(AsciiChar::Null));
907 s
908 })
909 }
910}
911
912#[cfg(feature = "std")]
914impl<'a> IntoAsciiString for &'a CStr {
915 #[inline]
916 unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
917 unsafe { AsciiString::from_ascii_unchecked(self.to_bytes()) }
919 }
920
921 fn into_ascii_string(self) -> Result<AsciiString, FromAsciiError<Self>> {
922 AsciiString::from_ascii(self.to_bytes_with_nul())
923 .map_err(|FromAsciiError { error, owner }| FromAsciiError {
924 owner: unsafe { CStr::from_ptr(owner.as_ptr().cast()) },
927 error,
928 })
929 .map(|mut s| {
930 let nul = s.pop();
931 debug_assert_eq!(nul, Some(AsciiChar::Null));
932 s
933 })
934 }
935}
936
937impl<'a, B> IntoAsciiString for Cow<'a, B>
938where
939 B: 'a + ToOwned + ?Sized,
940 &'a B: IntoAsciiString,
941 <B as ToOwned>::Owned: IntoAsciiString,
942{
943 #[inline]
944 unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
945 unsafe { IntoAsciiString::into_ascii_string_unchecked(self.into_owned()) }
947 }
948
949 fn into_ascii_string(self) -> Result<AsciiString, FromAsciiError<Self>> {
950 match self {
951 Cow::Owned(b) => {
952 IntoAsciiString::into_ascii_string(b).map_err(|FromAsciiError { error, owner }| {
953 FromAsciiError {
954 owner: Cow::Owned(owner),
955 error,
956 }
957 })
958 }
959 Cow::Borrowed(b) => {
960 IntoAsciiString::into_ascii_string(b).map_err(|FromAsciiError { error, owner }| {
961 FromAsciiError {
962 owner: Cow::Borrowed(owner),
963 error,
964 }
965 })
966 }
967 }
968 }
969}
970
971#[cfg(test)]
972mod tests {
973 use super::{AsciiString, IntoAsciiString};
974 use alloc::str::FromStr;
975 use alloc::string::{String, ToString};
976 use alloc::vec::Vec;
977 use alloc::boxed::Box;
978 #[cfg(feature = "std")]
979 use std::ffi::CString;
980 use {AsciiChar, AsciiStr};
981
982 #[test]
983 fn into_string() {
984 let v = AsciiString::from_ascii(&[40_u8, 32, 59][..]).unwrap();
985 assert_eq!(Into::<String>::into(v), "( ;".to_string());
986 }
987
988 #[test]
989 fn into_bytes() {
990 let v = AsciiString::from_ascii(&[40_u8, 32, 59][..]).unwrap();
991 assert_eq!(Into::<Vec<u8>>::into(v), vec![40_u8, 32, 59]);
992 }
993
994 #[test]
995 fn from_ascii_vec() {
996 let vec = vec![
997 AsciiChar::from_ascii('A').unwrap(),
998 AsciiChar::from_ascii('B').unwrap(),
999 ];
1000 assert_eq!(AsciiString::from(vec), AsciiString::from_str("AB").unwrap());
1001 }
1002
1003 #[test]
1004 #[cfg(feature = "std")]
1005 fn from_cstring() {
1006 let cstring = CString::new("baz").unwrap();
1007 let ascii_str = cstring.clone().into_ascii_string().unwrap();
1008 let expected_chars = &[AsciiChar::b, AsciiChar::a, AsciiChar::z];
1009 assert_eq!(ascii_str.len(), 3);
1010 assert_eq!(ascii_str.as_slice(), expected_chars);
1011
1012 let ascii_str_unchecked = unsafe { cstring.into_ascii_string_unchecked() };
1014 assert_eq!(ascii_str_unchecked.len(), 3);
1015 assert_eq!(ascii_str_unchecked.as_slice(), expected_chars);
1016
1017 let sparkle_heart_bytes = vec![240_u8, 159, 146, 150];
1018 let cstring = CString::new(sparkle_heart_bytes).unwrap();
1019 let cstr = &*cstring;
1020 let ascii_err = cstr.into_ascii_string().unwrap_err();
1021 assert_eq!(ascii_err.into_source(), &*cstring);
1022 }
1023
1024 #[test]
1025 #[cfg(feature = "std")]
1026 fn fmt_ascii_string() {
1027 let s = "abc".to_string().into_ascii_string().unwrap();
1028 assert_eq!(format!("{}", s), "abc".to_string());
1029 assert_eq!(format!("{:?}", s), "\"abc\"".to_string());
1030 }
1031
1032 #[test]
1033 fn write_fmt() {
1034 use alloc::{fmt, str};
1035
1036 let mut s0 = AsciiString::new();
1037 fmt::write(&mut s0, format_args!("Hello World")).unwrap();
1038 assert_eq!(s0, "Hello World");
1039
1040 let mut s1 = AsciiString::new();
1041 fmt::write(&mut s1, format_args!("{}", 9)).unwrap();
1042 assert_eq!(s1, "9");
1043
1044 let mut s2 = AsciiString::new();
1045 let sparkle_heart_bytes = [240, 159, 146, 150];
1046 let sparkle_heart = str::from_utf8(&sparkle_heart_bytes).unwrap();
1047 assert!(fmt::write(&mut s2, format_args!("{}", sparkle_heart)).is_err());
1048 }
1049
1050 #[test]
1051 fn to_and_from_box() {
1052 let string = "abc".into_ascii_string().unwrap();
1053 let converted: Box<AsciiStr> = Box::from(string.clone());
1054 let converted: AsciiString = converted.into();
1055 assert_eq!(string, converted);
1056 }
1057}