]> git.lizzy.rs Git - rust.git/blob - src/libcore/ascii.rs
Auto merge of #57714 - matthewjasper:wellformed-unreachable, r=pnkfelix
[rust.git] / src / libcore / ascii.rs
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 //! [`escape_default`]: fn.escape_default.html
11
12 #![stable(feature = "core_ascii", since = "1.26.0")]
13
14 use fmt;
15 use ops::Range;
16 use iter::FusedIterator;
17
18 /// An iterator over the escaped version of a byte.
19 ///
20 /// This `struct` is created by the [`escape_default`] function. See its
21 /// documentation for more.
22 ///
23 /// [`escape_default`]: fn.escape_default.html
24 #[stable(feature = "rust1", since = "1.0.0")]
25 pub struct EscapeDefault {
26     range: Range<usize>,
27     data: [u8; 4],
28 }
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")]
93 pub fn escape_default(c: u8) -> EscapeDefault {
94     let (data, len) = match c {
95         b'\t' => ([b'\\', b't', 0, 0], 2),
96         b'\r' => ([b'\\', b'r', 0, 0], 2),
97         b'\n' => ([b'\\', b'n', 0, 0], 2),
98         b'\\' => ([b'\\', b'\\', 0, 0], 2),
99         b'\'' => ([b'\\', b'\'', 0, 0], 2),
100         b'"' => ([b'\\', b'"', 0, 0], 2),
101         b'\x20' ..= b'\x7e' => ([c, 0, 0, 0], 1),
102         _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
103     };
104
105     return EscapeDefault { range: 0..len, data };
106
107     fn hexify(b: u8) -> u8 {
108         match b {
109             0 ..= 9 => b'0' + b,
110             _ => b'a' + b - 10,
111         }
112     }
113 }
114
115 #[stable(feature = "rust1", since = "1.0.0")]
116 impl Iterator for EscapeDefault {
117     type Item = u8;
118     fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
119     fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
120 }
121 #[stable(feature = "rust1", since = "1.0.0")]
122 impl DoubleEndedIterator for EscapeDefault {
123     fn next_back(&mut self) -> Option<u8> {
124         self.range.next_back().map(|i| self.data[i])
125     }
126 }
127 #[stable(feature = "rust1", since = "1.0.0")]
128 impl ExactSizeIterator for EscapeDefault {}
129 #[stable(feature = "fused", since = "1.26.0")]
130 impl FusedIterator for EscapeDefault {}
131
132 #[stable(feature = "std_debug", since = "1.16.0")]
133 impl fmt::Debug for EscapeDefault {
134     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135         f.pad("EscapeDefault { .. }")
136     }
137 }