• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Operations on ASCII strings and characters.
2 //!
3 //! Most string operations in Rust act on UTF-8 strings. However, at times it
4 //! makes more sense to only consider the ASCII character set for a specific
5 //! operation.
6 //!
7 //! The [`escape_default`] function provides an iterator over the bytes of an
8 //! escaped version of the character given.
9 
10 #![stable(feature = "core_ascii", since = "1.26.0")]
11 
12 use crate::escape;
13 use crate::fmt;
14 use crate::iter::FusedIterator;
15 use crate::num::NonZeroUsize;
16 
17 mod ascii_char;
18 #[unstable(feature = "ascii_char", issue = "110998")]
19 pub use ascii_char::AsciiChar as Char;
20 
21 /// An iterator over the escaped version of a byte.
22 ///
23 /// This `struct` is created by the [`escape_default`] function. See its
24 /// documentation for more.
25 #[must_use = "iterators are lazy and do nothing unless consumed"]
26 #[stable(feature = "rust1", since = "1.0.0")]
27 #[derive(Clone)]
28 pub struct EscapeDefault(escape::EscapeIterInner<4>);
29 
30 /// Returns an iterator that produces an escaped version of a `u8`.
31 ///
32 /// The default is chosen with a bias toward producing literals that are
33 /// legal in a variety of languages, including C++11 and similar C-family
34 /// languages. The exact rules are:
35 ///
36 /// * Tab is escaped as `\t`.
37 /// * Carriage return is escaped as `\r`.
38 /// * Line feed is escaped as `\n`.
39 /// * Single quote is escaped as `\'`.
40 /// * Double quote is escaped as `\"`.
41 /// * Backslash is escaped as `\\`.
42 /// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
43 ///   inclusive is not escaped.
44 /// * Any other chars are given hex escapes of the form '\xNN'.
45 /// * Unicode escapes are never generated by this function.
46 ///
47 /// # Examples
48 ///
49 /// ```
50 /// use std::ascii;
51 ///
52 /// let escaped = ascii::escape_default(b'0').next().unwrap();
53 /// assert_eq!(b'0', escaped);
54 ///
55 /// let mut escaped = ascii::escape_default(b'\t');
56 ///
57 /// assert_eq!(b'\\', escaped.next().unwrap());
58 /// assert_eq!(b't', escaped.next().unwrap());
59 ///
60 /// let mut escaped = ascii::escape_default(b'\r');
61 ///
62 /// assert_eq!(b'\\', escaped.next().unwrap());
63 /// assert_eq!(b'r', escaped.next().unwrap());
64 ///
65 /// let mut escaped = ascii::escape_default(b'\n');
66 ///
67 /// assert_eq!(b'\\', escaped.next().unwrap());
68 /// assert_eq!(b'n', escaped.next().unwrap());
69 ///
70 /// let mut escaped = ascii::escape_default(b'\'');
71 ///
72 /// assert_eq!(b'\\', escaped.next().unwrap());
73 /// assert_eq!(b'\'', escaped.next().unwrap());
74 ///
75 /// let mut escaped = ascii::escape_default(b'"');
76 ///
77 /// assert_eq!(b'\\', escaped.next().unwrap());
78 /// assert_eq!(b'"', escaped.next().unwrap());
79 ///
80 /// let mut escaped = ascii::escape_default(b'\\');
81 ///
82 /// assert_eq!(b'\\', escaped.next().unwrap());
83 /// assert_eq!(b'\\', escaped.next().unwrap());
84 ///
85 /// let mut escaped = ascii::escape_default(b'\x9d');
86 ///
87 /// assert_eq!(b'\\', escaped.next().unwrap());
88 /// assert_eq!(b'x', escaped.next().unwrap());
89 /// assert_eq!(b'9', escaped.next().unwrap());
90 /// assert_eq!(b'd', escaped.next().unwrap());
91 /// ```
92 #[stable(feature = "rust1", since = "1.0.0")]
escape_default(c: u8) -> EscapeDefault93 pub fn escape_default(c: u8) -> EscapeDefault {
94     let mut data = [Char::Null; 4];
95     let range = escape::escape_ascii_into(&mut data, c);
96     EscapeDefault(escape::EscapeIterInner::new(data, range))
97 }
98 
99 #[stable(feature = "rust1", since = "1.0.0")]
100 impl Iterator for EscapeDefault {
101     type Item = u8;
102 
103     #[inline]
next(&mut self) -> Option<u8>104     fn next(&mut self) -> Option<u8> {
105         self.0.next()
106     }
107 
108     #[inline]
size_hint(&self) -> (usize, Option<usize>)109     fn size_hint(&self) -> (usize, Option<usize>) {
110         let n = self.0.len();
111         (n, Some(n))
112     }
113 
114     #[inline]
count(self) -> usize115     fn count(self) -> usize {
116         self.0.len()
117     }
118 
119     #[inline]
last(mut self) -> Option<u8>120     fn last(mut self) -> Option<u8> {
121         self.0.next_back()
122     }
123 
124     #[inline]
advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize>125     fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
126         self.0.advance_by(n)
127     }
128 }
129 
130 #[stable(feature = "rust1", since = "1.0.0")]
131 impl DoubleEndedIterator for EscapeDefault {
132     #[inline]
next_back(&mut self) -> Option<u8>133     fn next_back(&mut self) -> Option<u8> {
134         self.0.next_back()
135     }
136 
137     #[inline]
advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize>138     fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
139         self.0.advance_back_by(n)
140     }
141 }
142 
143 #[stable(feature = "rust1", since = "1.0.0")]
144 impl ExactSizeIterator for EscapeDefault {
145     #[inline]
len(&self) -> usize146     fn len(&self) -> usize {
147         self.0.len()
148     }
149 }
150 
151 #[stable(feature = "fused", since = "1.26.0")]
152 impl FusedIterator for EscapeDefault {}
153 
154 #[stable(feature = "ascii_escape_display", since = "1.39.0")]
155 impl fmt::Display for EscapeDefault {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result156     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157         f.write_str(self.0.as_str())
158     }
159 }
160 
161 #[stable(feature = "std_debug", since = "1.16.0")]
162 impl fmt::Debug for EscapeDefault {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result163     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164         f.debug_struct("EscapeDefault").finish_non_exhaustive()
165     }
166 }
167