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" )] |
93 | pub fn escape_default(c: u8) -> EscapeDefault { |
94 | let mut data: [AsciiChar; 4] = [Char::Null; 4]; |
95 | let range: Range = escape::escape_ascii_into(&mut data, byte:c); |
96 | EscapeDefault(escape::EscapeIterInner::new(data, alive:range)) |
97 | } |
98 | |
99 | impl EscapeDefault { |
100 | pub(crate) fn empty() -> Self { |
101 | let data: [AsciiChar; 4] = [Char::Null; 4]; |
102 | EscapeDefault(escape::EscapeIterInner::new(data, alive:0..0)) |
103 | } |
104 | |
105 | pub(crate) fn as_str(&self) -> &str { |
106 | self.0.as_str() |
107 | } |
108 | } |
109 | |
110 | #[stable (feature = "rust1" , since = "1.0.0" )] |
111 | impl Iterator for EscapeDefault { |
112 | type Item = u8; |
113 | |
114 | #[inline ] |
115 | fn next(&mut self) -> Option<u8> { |
116 | self.0.next() |
117 | } |
118 | |
119 | #[inline ] |
120 | fn size_hint(&self) -> (usize, Option<usize>) { |
121 | let n = self.0.len(); |
122 | (n, Some(n)) |
123 | } |
124 | |
125 | #[inline ] |
126 | fn count(self) -> usize { |
127 | self.0.len() |
128 | } |
129 | |
130 | #[inline ] |
131 | fn last(mut self) -> Option<u8> { |
132 | self.0.next_back() |
133 | } |
134 | |
135 | #[inline ] |
136 | fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { |
137 | self.0.advance_by(n) |
138 | } |
139 | } |
140 | |
141 | #[stable (feature = "rust1" , since = "1.0.0" )] |
142 | impl DoubleEndedIterator for EscapeDefault { |
143 | #[inline ] |
144 | fn next_back(&mut self) -> Option<u8> { |
145 | self.0.next_back() |
146 | } |
147 | |
148 | #[inline ] |
149 | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { |
150 | self.0.advance_back_by(n) |
151 | } |
152 | } |
153 | |
154 | #[stable (feature = "rust1" , since = "1.0.0" )] |
155 | impl ExactSizeIterator for EscapeDefault { |
156 | #[inline ] |
157 | fn len(&self) -> usize { |
158 | self.0.len() |
159 | } |
160 | } |
161 | |
162 | #[stable (feature = "fused" , since = "1.26.0" )] |
163 | impl FusedIterator for EscapeDefault {} |
164 | |
165 | #[stable (feature = "ascii_escape_display" , since = "1.39.0" )] |
166 | impl fmt::Display for EscapeDefault { |
167 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
168 | f.write_str(self.0.as_str()) |
169 | } |
170 | } |
171 | |
172 | #[stable (feature = "std_debug" , since = "1.16.0" )] |
173 | impl fmt::Debug for EscapeDefault { |
174 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
175 | f.debug_struct(name:"EscapeDefault" ).finish_non_exhaustive() |
176 | } |
177 | } |
178 | |