1 //! Operations on ASCII strings and characters.
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
7 //! The [`escape_default`] function provides an iterator over the bytes of an
8 //! escaped version of the character given.
10 #![stable(feature = "core_ascii", since = "1.26.0")]
13 use crate::iter::FusedIterator;
14 use crate::ops::Range;
15 use crate::str::from_utf8_unchecked;
17 /// An iterator over the escaped version of a byte.
19 /// This `struct` is created by the [`escape_default`] function. See its
20 /// documentation for more.
21 #[stable(feature = "rust1", since = "1.0.0")]
23 pub struct EscapeDefault {
28 /// Returns an iterator that produces an escaped version of a `u8`.
30 /// The default is chosen with a bias toward producing literals that are
31 /// legal in a variety of languages, including C++11 and similar C-family
32 /// languages. The exact rules are:
34 /// * Tab is escaped as `\t`.
35 /// * Carriage return is escaped as `\r`.
36 /// * Line feed is escaped as `\n`.
37 /// * Single quote is escaped as `\'`.
38 /// * Double quote is escaped as `\"`.
39 /// * Backslash is escaped as `\\`.
40 /// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
41 /// inclusive is not escaped.
42 /// * Any other chars are given hex escapes of the form '\xNN'.
43 /// * Unicode escapes are never generated by this function.
50 /// let escaped = ascii::escape_default(b'0').next().unwrap();
51 /// assert_eq!(b'0', escaped);
53 /// let mut escaped = ascii::escape_default(b'\t');
55 /// assert_eq!(b'\\', escaped.next().unwrap());
56 /// assert_eq!(b't', escaped.next().unwrap());
58 /// let mut escaped = ascii::escape_default(b'\r');
60 /// assert_eq!(b'\\', escaped.next().unwrap());
61 /// assert_eq!(b'r', escaped.next().unwrap());
63 /// let mut escaped = ascii::escape_default(b'\n');
65 /// assert_eq!(b'\\', escaped.next().unwrap());
66 /// assert_eq!(b'n', escaped.next().unwrap());
68 /// let mut escaped = ascii::escape_default(b'\'');
70 /// assert_eq!(b'\\', escaped.next().unwrap());
71 /// assert_eq!(b'\'', escaped.next().unwrap());
73 /// let mut escaped = ascii::escape_default(b'"');
75 /// assert_eq!(b'\\', escaped.next().unwrap());
76 /// assert_eq!(b'"', escaped.next().unwrap());
78 /// let mut escaped = ascii::escape_default(b'\\');
80 /// assert_eq!(b'\\', escaped.next().unwrap());
81 /// assert_eq!(b'\\', escaped.next().unwrap());
83 /// let mut escaped = ascii::escape_default(b'\x9d');
85 /// assert_eq!(b'\\', escaped.next().unwrap());
86 /// assert_eq!(b'x', escaped.next().unwrap());
87 /// assert_eq!(b'9', escaped.next().unwrap());
88 /// assert_eq!(b'd', escaped.next().unwrap());
90 #[stable(feature = "rust1", since = "1.0.0")]
91 pub fn escape_default(c: u8) -> EscapeDefault {
92 let (data, len) = match c {
93 b'\t' => ([b'\\', b't', 0, 0], 2),
94 b'\r' => ([b'\\', b'r', 0, 0], 2),
95 b'\n' => ([b'\\', b'n', 0, 0], 2),
96 b'\\' => ([b'\\', b'\\', 0, 0], 2),
97 b'\'' => ([b'\\', b'\'', 0, 0], 2),
98 b'"' => ([b'\\', b'"', 0, 0], 2),
99 b'\x20'..=b'\x7e' => ([c, 0, 0, 0], 1),
100 _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
103 return EscapeDefault { range: 0..len, data };
105 fn hexify(b: u8) -> u8 {
113 #[stable(feature = "rust1", since = "1.0.0")]
114 impl Iterator for EscapeDefault {
116 fn next(&mut self) -> Option<u8> {
117 self.range.next().map(|i| self.data[i])
119 fn size_hint(&self) -> (usize, Option<usize>) {
120 self.range.size_hint()
122 fn last(mut self) -> Option<u8> {
126 #[stable(feature = "rust1", since = "1.0.0")]
127 impl DoubleEndedIterator for EscapeDefault {
128 fn next_back(&mut self) -> Option<u8> {
129 self.range.next_back().map(|i| self.data[i])
132 #[stable(feature = "rust1", since = "1.0.0")]
133 impl ExactSizeIterator for EscapeDefault {}
134 #[stable(feature = "fused", since = "1.26.0")]
135 impl FusedIterator for EscapeDefault {}
137 #[stable(feature = "ascii_escape_display", since = "1.39.0")]
138 impl fmt::Display for EscapeDefault {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 // SAFETY: ok because `escape_default` created only valid utf-8 data
141 f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
145 #[stable(feature = "std_debug", since = "1.16.0")]
146 impl fmt::Debug for EscapeDefault {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 f.debug_struct("EscapeDefault").finish_non_exhaustive()