ascii/
ascii_string.rs

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/// A growable string stored as an ASCII encoded buffer.
23#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[repr(transparent)]
25pub struct AsciiString {
26    vec: Vec<AsciiChar>,
27}
28
29impl AsciiString {
30    /// Creates a new, empty ASCII string buffer without allocating.
31    ///
32    /// # Examples
33    /// ```
34    /// # use ascii::AsciiString;
35    /// let mut s = AsciiString::new();
36    /// ```
37    #[inline]
38    #[must_use]
39    pub const fn new() -> Self {
40        AsciiString { vec: Vec::new() }
41    }
42
43    /// Creates a new ASCII string buffer with the given capacity.
44    /// The string will be able to hold exactly `capacity` bytes without reallocating.
45    /// If `capacity` is 0, the ASCII string will not allocate.
46    ///
47    /// # Examples
48    /// ```
49    /// # use ascii::AsciiString;
50    /// let mut s = AsciiString::with_capacity(10);
51    /// ```
52    #[inline]
53    #[must_use]
54    pub fn with_capacity(capacity: usize) -> Self {
55        AsciiString {
56            vec: Vec::with_capacity(capacity),
57        }
58    }
59
60    /// Creates a new `AsciiString` from a length, capacity and pointer.
61    ///
62    /// # Safety
63    ///
64    /// This is highly unsafe, due to the number of invariants that aren't checked:
65    ///
66    /// * The memory at `buf` need to have been previously allocated by the same allocator this
67    ///   library uses, with an alignment of 1.
68    /// * `length` needs to be less than or equal to `capacity`.
69    /// * `capacity` needs to be the correct value.
70    /// * `buf` must have `length` valid ascii elements and contain a total of `capacity` total,
71    ///   possibly, uninitialized, elements.
72    /// * Nothing else must be using the memory `buf` points to.
73    ///
74    /// Violating these may cause problems like corrupting the allocator's internal data structures.
75    ///
76    /// # Examples
77    ///
78    /// Basic usage:
79    ///
80    /// ```
81    /// # use ascii::AsciiString;
82    /// use std::mem;
83    ///
84    /// unsafe {
85    ///    let mut s = AsciiString::from_ascii("hello").unwrap();
86    ///    let ptr = s.as_mut_ptr();
87    ///    let len = s.len();
88    ///    let capacity = s.capacity();
89    ///
90    ///    mem::forget(s);
91    ///
92    ///    let s = AsciiString::from_raw_parts(ptr, len, capacity);
93    ///
94    ///    assert_eq!(AsciiString::from_ascii("hello").unwrap(), s);
95    /// }
96    /// ```
97    #[inline]
98    #[must_use]
99    pub unsafe fn from_raw_parts(buf: *mut AsciiChar, length: usize, capacity: usize) -> Self {
100        AsciiString {
101            // SAFETY: Caller guarantees that `buf` was previously allocated by this library,
102            //         that `buf` contains `length` valid ascii elements and has a total capacity
103            //         of `capacity` elements, and that nothing else is using the momory.
104            vec: unsafe { Vec::from_raw_parts(buf, length, capacity) },
105        }
106    }
107
108    /// Converts a vector of bytes to an `AsciiString` without checking for non-ASCII characters.
109    ///
110    /// # Safety
111    /// This function is unsafe because it does not check that the bytes passed to it are valid
112    /// ASCII characters. If this constraint is violated, it may cause memory unsafety issues with
113    /// future of the `AsciiString`, as the rest of this library assumes that `AsciiString`s are
114    /// ASCII encoded.
115    #[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        // SAFETY: The caller guarantees all bytes are valid ascii bytes.
123        let ptr = bytes.as_mut_ptr().cast::<AsciiChar>();
124        let length = bytes.len();
125        let capacity = bytes.capacity();
126        mem::forget(bytes);
127
128        // SAFETY: We guarantee all invariants, as we got the
129        //         pointer, length and capacity from a `Vec`,
130        //         and we also guarantee the pointer is valid per
131        //         the `SAFETY` notice above.
132        let vec = Vec::from_raw_parts(ptr, length, capacity);
133
134        Self { vec }
135    }
136
137    /// Converts anything that can represent a byte buffer into an `AsciiString`.
138    ///
139    /// # Errors
140    /// Returns the byte buffer if not all of the bytes are ASCII characters.
141    ///
142    /// # Examples
143    /// ```
144    /// # use ascii::AsciiString;
145    /// let foo = AsciiString::from_ascii("foo".to_string()).unwrap();
146    /// let err = AsciiString::from_ascii("Ŋ".to_string()).unwrap_err();
147    /// assert_eq!(foo.as_str(), "foo");
148    /// assert_eq!(err.into_source(), "Ŋ");
149    /// ```
150    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            // SAFETY: `as_ascii_str` guarantees all bytes are valid ascii bytes.
156            Ok(_) => Ok(unsafe { AsciiString::from_ascii_unchecked(bytes) }),
157            Err(e) => Err(FromAsciiError {
158                error: e,
159                owner: bytes,
160            }),
161        }
162    }
163
164    /// Pushes the given ASCII string onto this ASCII string buffer.
165    ///
166    /// # Examples
167    /// ```
168    /// # use ascii::{AsciiString, AsAsciiStr};
169    /// use std::str::FromStr;
170    /// let mut s = AsciiString::from_str("foo").unwrap();
171    /// s.push_str("bar".as_ascii_str().unwrap());
172    /// assert_eq!(s, "foobar".as_ascii_str().unwrap());
173    /// ```
174    #[inline]
175    pub fn push_str(&mut self, string: &AsciiStr) {
176        self.vec.extend(string.chars());
177    }
178
179    /// Inserts the given ASCII string at the given place in this ASCII string buffer.
180    ///
181    /// # Panics
182    ///
183    /// Panics if `idx` is larger than the `AsciiString`'s length.
184    ///
185    /// # Examples
186    /// ```
187    /// # use ascii::{AsciiString, AsAsciiStr};
188    /// use std::str::FromStr;
189    /// let mut s = AsciiString::from_str("abc").unwrap();
190    /// s.insert_str(1, "def".as_ascii_str().unwrap());
191    /// assert_eq!(&*s, "adefbc");
192    #[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    /// Returns the number of bytes that this ASCII string buffer can hold without reallocating.
199    ///
200    /// # Examples
201    /// ```
202    /// # use ascii::AsciiString;
203    /// let s = String::with_capacity(10);
204    /// assert!(s.capacity() >= 10);
205    /// ```
206    #[inline]
207    #[must_use]
208    pub fn capacity(&self) -> usize {
209        self.vec.capacity()
210    }
211
212    /// Reserves capacity for at least `additional` more bytes to be inserted in the given
213    /// `AsciiString`. The collection may reserve more space to avoid frequent reallocations.
214    ///
215    /// # Panics
216    /// Panics if the new capacity overflows `usize`.
217    ///
218    /// # Examples
219    /// ```
220    /// # use ascii::AsciiString;
221    /// let mut s = AsciiString::new();
222    /// s.reserve(10);
223    /// assert!(s.capacity() >= 10);
224    /// ```
225    #[inline]
226    pub fn reserve(&mut self, additional: usize) {
227        self.vec.reserve(additional);
228    }
229
230    /// Reserves the minimum capacity for exactly `additional` more bytes to be inserted in the
231    /// given `AsciiString`. Does nothing if the capacity is already sufficient.
232    ///
233    /// Note that the allocator may give the collection more space than it requests. Therefore
234    /// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
235    /// insertions are expected.
236    ///
237    /// # Panics
238    /// Panics if the new capacity overflows `usize`.
239    ///
240    /// # Examples
241    /// ```
242    /// # use ascii::AsciiString;
243    /// let mut s = AsciiString::new();
244    /// s.reserve_exact(10);
245    /// assert!(s.capacity() >= 10);
246    /// ```
247    #[inline]
248
249    pub fn reserve_exact(&mut self, additional: usize) {
250        self.vec.reserve_exact(additional);
251    }
252
253    /// Shrinks the capacity of this ASCII string buffer to match it's length.
254    ///
255    /// # Examples
256    /// ```
257    /// # use ascii::AsciiString;
258    /// use std::str::FromStr;
259    /// let mut s = AsciiString::from_str("foo").unwrap();
260    /// s.reserve(100);
261    /// assert!(s.capacity() >= 100);
262    /// s.shrink_to_fit();
263    /// assert_eq!(s.capacity(), 3);
264    /// ```
265    #[inline]
266
267    pub fn shrink_to_fit(&mut self) {
268        self.vec.shrink_to_fit();
269    }
270
271    /// Adds the given ASCII character to the end of the ASCII string.
272    ///
273    /// # Examples
274    /// ```
275    /// # use ascii::{ AsciiChar, AsciiString};
276    /// let mut s = AsciiString::from_ascii("abc").unwrap();
277    /// s.push(AsciiChar::from_ascii('1').unwrap());
278    /// s.push(AsciiChar::from_ascii('2').unwrap());
279    /// s.push(AsciiChar::from_ascii('3').unwrap());
280    /// assert_eq!(s, "abc123");
281    /// ```
282    #[inline]
283
284    pub fn push(&mut self, ch: AsciiChar) {
285        self.vec.push(ch);
286    }
287
288    /// Shortens a ASCII string to the specified length.
289    ///
290    /// # Panics
291    /// Panics if `new_len` > current length.
292    ///
293    /// # Examples
294    /// ```
295    /// # use ascii::AsciiString;
296    /// let mut s = AsciiString::from_ascii("hello").unwrap();
297    /// s.truncate(2);
298    /// assert_eq!(s, "he");
299    /// ```
300    #[inline]
301
302    pub fn truncate(&mut self, new_len: usize) {
303        self.vec.truncate(new_len);
304    }
305
306    /// Removes the last character from the ASCII string buffer and returns it.
307    /// Returns `None` if this string buffer is empty.
308    ///
309    /// # Examples
310    /// ```
311    /// # use ascii::AsciiString;
312    /// let mut s = AsciiString::from_ascii("foo").unwrap();
313    /// assert_eq!(s.pop().map(|c| c.as_char()), Some('o'));
314    /// assert_eq!(s.pop().map(|c| c.as_char()), Some('o'));
315    /// assert_eq!(s.pop().map(|c| c.as_char()), Some('f'));
316    /// assert_eq!(s.pop(), None);
317    /// ```
318    #[inline]
319    #[must_use]
320    pub fn pop(&mut self) -> Option<AsciiChar> {
321        self.vec.pop()
322    }
323
324    /// Removes the ASCII character at position `idx` from the buffer and returns it.
325    ///
326    /// # Warning
327    /// This is an O(n) operation as it requires copying every element in the buffer.
328    ///
329    /// # Panics
330    /// If `idx` is out of bounds this function will panic.
331    ///
332    /// # Examples
333    /// ```
334    /// # use ascii::AsciiString;
335    /// let mut s = AsciiString::from_ascii("foo").unwrap();
336    /// assert_eq!(s.remove(0).as_char(), 'f');
337    /// assert_eq!(s.remove(1).as_char(), 'o');
338    /// assert_eq!(s.remove(0).as_char(), 'o');
339    /// ```
340    #[inline]
341    #[must_use]
342    pub fn remove(&mut self, idx: usize) -> AsciiChar {
343        self.vec.remove(idx)
344    }
345
346    /// Inserts an ASCII character into the buffer at position `idx`.
347    ///
348    /// # Warning
349    /// This is an O(n) operation as it requires copying every element in the buffer.
350    ///
351    /// # Panics
352    /// If `idx` is out of bounds this function will panic.
353    ///
354    /// # Examples
355    /// ```
356    /// # use ascii::{AsciiString,AsciiChar};
357    /// let mut s = AsciiString::from_ascii("foo").unwrap();
358    /// s.insert(2, AsciiChar::b);
359    /// assert_eq!(s, "fobo");
360    /// ```
361    #[inline]
362
363    pub fn insert(&mut self, idx: usize, ch: AsciiChar) {
364        self.vec.insert(idx, ch);
365    }
366
367    /// Returns the number of bytes in this ASCII string.
368    ///
369    /// # Examples
370    /// ```
371    /// # use ascii::AsciiString;
372    /// let s = AsciiString::from_ascii("foo").unwrap();
373    /// assert_eq!(s.len(), 3);
374    /// ```
375    #[inline]
376    #[must_use]
377    pub fn len(&self) -> usize {
378        self.vec.len()
379    }
380
381    /// Returns true if the ASCII string contains zero bytes.
382    ///
383    /// # Examples
384    /// ```
385    /// # use ascii::{AsciiChar, AsciiString};
386    /// let mut s = AsciiString::new();
387    /// assert!(s.is_empty());
388    /// s.push(AsciiChar::from_ascii('a').unwrap());
389    /// assert!(!s.is_empty());
390    /// ```
391    #[inline]
392    #[must_use]
393    pub fn is_empty(&self) -> bool {
394        self.len() == 0
395    }
396
397    /// Truncates the ASCII string, setting length (but not capacity) to zero.
398    ///
399    /// # Examples
400    /// ```
401    /// # use ascii::AsciiString;
402    /// let mut s = AsciiString::from_ascii("foo").unwrap();
403    /// s.clear();
404    /// assert!(s.is_empty());
405    /// ```
406    #[inline]
407
408    pub fn clear(&mut self) {
409        self.vec.clear();
410    }
411
412    /// Converts this [`AsciiString`] into a [`Box`]`<`[`AsciiStr`]`>`.
413    ///
414    /// This will drop any excess capacity
415    #[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        // SAFETY: All ascii bytes are valid `u8`, as we are `repr(u8)`.
504        // Note: We forget `self` to avoid `self.vec` from being deallocated.
505        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        // SAFETY: We guarantee all invariants due to getting `ptr`, `length`
511        //         and `capacity` from a `Vec`. We also guarantee `ptr` is valid
512        //         due to the `SAFETY` block above.
513        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        // SAFETY: All ascii bytes are `utf8`.
541        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        // SAFETY: AsciiStr is repr(transparent) and thus has the same layout as [AsciiChar]
563        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        // SAFETY: AsciiStr is repr(transparent) and thus has the same layout as [AsciiChar]
571        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
657/// Please note that the `std::fmt::Result` returned by these methods does not support
658/// transmission of an error other than that an error occurred.
659impl 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)] // In `Index`, if it's out of bounds, panic is the default
716impl<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)] // In `IndexMut`, if it's out of bounds, panic is the default
729impl<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/// A possible error value when converting an `AsciiString` from a byte vector or string.
740/// It wraps an `AsAsciiStrError` which you can get through the `ascii_error()` method.
741///
742/// This is the error type for `AsciiString::from_ascii()` and
743/// `IntoAsciiString::into_ascii_string()`. They will never clone or touch the content of the
744/// original type; It can be extracted by the `into_source` method.
745///
746/// #Examples
747/// ```
748/// # use ascii::IntoAsciiString;
749/// let err = "bø!".to_string().into_ascii_string().unwrap_err();
750/// assert_eq!(err.ascii_error().valid_up_to(), 1);
751/// assert_eq!(err.into_source(), "bø!".to_string());
752/// ```
753#[derive(Clone, Copy, PartialEq, Eq)]
754pub struct FromAsciiError<O> {
755    error: AsAsciiStrError,
756    owner: O,
757}
758impl<O> FromAsciiError<O> {
759    /// Get the position of the first non-ASCII byte or character.
760    #[inline]
761    #[must_use]
762    pub fn ascii_error(&self) -> AsAsciiStrError {
763        self.error
764    }
765    /// Get back the original, unmodified type.
766    #[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)] // TODO: Remove deprecation once the earliest version we support deprecates this method.
788    fn description(&self) -> &str {
789        self.error.description()
790    }
791    /// Always returns an `AsAsciiStrError`
792    fn cause(&self) -> Option<&dyn Error> {
793        Some(&self.error as &dyn Error)
794    }
795}
796
797/// Convert vectors into `AsciiString`.
798pub trait IntoAsciiString: Sized {
799    /// Convert to `AsciiString` without checking for non-ASCII characters.
800    ///
801    /// # Safety
802    /// If `self` contains non-ascii characters, calling this function is
803    /// undefined behavior.
804    unsafe fn into_ascii_string_unchecked(self) -> AsciiString;
805
806    /// Convert to `AsciiString`.
807    ///
808    /// # Errors
809    /// If `self` contains non-ascii characters, this will return `Err`
810    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                // SAFETY: Caller guarantees `self` only has valid ascii bytes
852                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                // SAFETY: Caller guarantees `self` only has valid ascii bytes
867                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/// # Notes
885/// The trailing null byte `CString` has will be removed during this conversion.
886#[cfg(feature = "std")]
887impl IntoAsciiString for CString {
888    #[inline]
889    unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
890        // SAFETY: Caller guarantees `self` only has valid ascii bytes
891        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                    // SAFETY: We don't discard the NULL byte from the original
899                    //         string, so we ensure that it's null terminated
900                    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/// Note that the trailing null byte will be removed in the conversion.
913#[cfg(feature = "std")]
914impl<'a> IntoAsciiString for &'a CStr {
915    #[inline]
916    unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
917        // SAFETY: Caller guarantees `self` only has valid ascii bytes
918        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                // SAFETY: We don't discard the NULL byte from the original
925                //         string, so we ensure that it's null terminated
926                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        // SAFETY: Caller guarantees `self` only has valid ascii bytes
946        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        // SAFETY: "baz" only contains valid ascii characters.
1013        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}