| 
1 | 1 | //! Operations on ASCII `[u8]`.  | 
2 | 2 | 
  | 
 | 3 | +use crate::ascii;  | 
 | 4 | +use crate::fmt::{self, Write};  | 
3 | 5 | use crate::iter;  | 
4 | 6 | use crate::mem;  | 
 | 7 | +use crate::ops;  | 
5 | 8 | 
 
  | 
6 | 9 | #[lang = "slice_u8"]  | 
7 | 10 | #[cfg(not(test))]  | 
@@ -56,6 +59,95 @@ impl [u8] {  | 
56 | 59 |             byte.make_ascii_lowercase();  | 
57 | 60 |         }  | 
58 | 61 |     }  | 
 | 62 | + | 
 | 63 | +    /// Returns an iterator that produces an escaped version of this slice,  | 
 | 64 | +    /// treating it as an ASCII string.  | 
 | 65 | +    ///  | 
 | 66 | +    /// # Examples  | 
 | 67 | +    ///  | 
 | 68 | +    /// ```  | 
 | 69 | +    /// #![feature(inherent_ascii_escape)]  | 
 | 70 | +    ///  | 
 | 71 | +    /// let s = b"0\t\r\n'\"\\\x9d";  | 
 | 72 | +    /// let escaped = s.escape_ascii().to_string();  | 
 | 73 | +    /// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d");  | 
 | 74 | +    /// ```  | 
 | 75 | +    #[unstable(feature = "inherent_ascii_escape", issue = "77174")]  | 
 | 76 | +    pub fn escape_ascii(&self) -> EscapeAscii<'_> {  | 
 | 77 | +        EscapeAscii { inner: self.iter().flat_map(EscapeByte) }  | 
 | 78 | +    }  | 
 | 79 | +}  | 
 | 80 | + | 
 | 81 | +impl_fn_for_zst! {  | 
 | 82 | +    #[derive(Clone)]  | 
 | 83 | +    struct EscapeByte impl Fn = |byte: &u8| -> ascii::EscapeDefault {  | 
 | 84 | +        ascii::escape_default(*byte)  | 
 | 85 | +    };  | 
 | 86 | +}  | 
 | 87 | + | 
 | 88 | +/// An iterator over the escaped version of a byte slice.  | 
 | 89 | +///  | 
 | 90 | +/// This `struct` is created by the [`slice::escape_ascii`] method. See its  | 
 | 91 | +/// documentation for more information.  | 
 | 92 | +#[unstable(feature = "inherent_ascii_escape", issue = "77174")]  | 
 | 93 | +#[derive(Clone)]  | 
 | 94 | +pub struct EscapeAscii<'a> {  | 
 | 95 | +    inner: iter::FlatMap<super::Iter<'a, u8>, ascii::EscapeDefault, EscapeByte>,  | 
 | 96 | +}  | 
 | 97 | + | 
 | 98 | +#[unstable(feature = "inherent_ascii_escape", issue = "77174")]  | 
 | 99 | +impl<'a> iter::Iterator for EscapeAscii<'a> {  | 
 | 100 | +    type Item = u8;  | 
 | 101 | +    #[inline]  | 
 | 102 | +    fn next(&mut self) -> Option<u8> {  | 
 | 103 | +        self.inner.next()  | 
 | 104 | +    }  | 
 | 105 | +    #[inline]  | 
 | 106 | +    fn size_hint(&self) -> (usize, Option<usize>) {  | 
 | 107 | +        self.inner.size_hint()  | 
 | 108 | +    }  | 
 | 109 | +    #[inline]  | 
 | 110 | +    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R  | 
 | 111 | +    where  | 
 | 112 | +        Fold: FnMut(Acc, Self::Item) -> R,  | 
 | 113 | +        R: ops::Try<Ok = Acc>,  | 
 | 114 | +    {  | 
 | 115 | +        self.inner.try_fold(init, fold)  | 
 | 116 | +    }  | 
 | 117 | +    #[inline]  | 
 | 118 | +    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc  | 
 | 119 | +    where  | 
 | 120 | +        Fold: FnMut(Acc, Self::Item) -> Acc,  | 
 | 121 | +    {  | 
 | 122 | +        self.inner.fold(init, fold)  | 
 | 123 | +    }  | 
 | 124 | +    #[inline]  | 
 | 125 | +    fn last(mut self) -> Option<u8> {  | 
 | 126 | +        self.next_back()  | 
 | 127 | +    }  | 
 | 128 | +}  | 
 | 129 | + | 
 | 130 | +#[unstable(feature = "inherent_ascii_escape", issue = "77174")]  | 
 | 131 | +impl<'a> iter::DoubleEndedIterator for EscapeAscii<'a> {  | 
 | 132 | +    fn next_back(&mut self) -> Option<u8> {  | 
 | 133 | +        self.inner.next_back()  | 
 | 134 | +    }  | 
 | 135 | +}  | 
 | 136 | +#[unstable(feature = "inherent_ascii_escape", issue = "77174")]  | 
 | 137 | +impl<'a> iter::ExactSizeIterator for EscapeAscii<'a> {}  | 
 | 138 | +#[unstable(feature = "inherent_ascii_escape", issue = "77174")]  | 
 | 139 | +impl<'a> iter::FusedIterator for EscapeAscii<'a> {}  | 
 | 140 | +#[unstable(feature = "inherent_ascii_escape", issue = "77174")]  | 
 | 141 | +impl<'a> fmt::Display for EscapeAscii<'a> {  | 
 | 142 | +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {  | 
 | 143 | +        self.clone().try_for_each(|b| f.write_char(b as char))  | 
 | 144 | +    }  | 
 | 145 | +}  | 
 | 146 | +#[unstable(feature = "inherent_ascii_escape", issue = "77174")]  | 
 | 147 | +impl<'a> fmt::Debug for EscapeAscii<'a> {  | 
 | 148 | +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {  | 
 | 149 | +        f.pad("EscapeAscii { .. }")  | 
 | 150 | +    }  | 
59 | 151 | }  | 
60 | 152 | 
 
  | 
61 | 153 | /// Returns `true` if any byte in the word `v` is nonascii (>= 128). Snarfed  | 
 | 
0 commit comments