core/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#![stable(feature = "core_ascii", since = "1.26.0")]
11
12use crate::escape::{AlwaysEscaped, EscapeIterInner};
13use crate::fmt;
14use crate::iter::FusedIterator;
15use crate::num::NonZero;
16
17mod ascii_char;
18#[doc(alias("AsciiChar"))]
19#[unstable(feature = "ascii_char", issue = "110998")]
20pub use ascii_char::AsciiChar as Char;
21
22/// An iterator over the escaped version of a byte.
23///
24/// This `struct` is created by the [`escape_default`] function. See its
25/// documentation for more.
26#[must_use = "iterators are lazy and do nothing unless consumed"]
27#[stable(feature = "rust1", since = "1.0.0")]
28#[derive(Clone)]
29#[ferrocene::prevalidated]
30pub struct EscapeDefault(EscapeIterInner<4, AlwaysEscaped>);
31
32/// Returns an iterator that produces an escaped version of a `u8`.
33///
34/// The default is chosen with a bias toward producing literals that are
35/// legal in a variety of languages, including C++11 and similar C-family
36/// languages. The exact rules are:
37///
38/// * Tab is escaped as `\t`.
39/// * Carriage return is escaped as `\r`.
40/// * Line feed is escaped as `\n`.
41/// * Single quote is escaped as `\'`.
42/// * Double quote is escaped as `\"`.
43/// * Backslash is escaped as `\\`.
44/// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
45/// inclusive is not escaped.
46/// * Any other chars are given hex escapes of the form '\xNN'.
47/// * Unicode escapes are never generated by this function.
48///
49/// # Examples
50///
51/// ```
52/// use std::ascii;
53///
54/// let escaped = ascii::escape_default(b'0').next().unwrap();
55/// assert_eq!(b'0', escaped);
56///
57/// let mut escaped = ascii::escape_default(b'\t');
58///
59/// assert_eq!(b'\\', escaped.next().unwrap());
60/// assert_eq!(b't', escaped.next().unwrap());
61///
62/// let mut escaped = ascii::escape_default(b'\r');
63///
64/// assert_eq!(b'\\', escaped.next().unwrap());
65/// assert_eq!(b'r', escaped.next().unwrap());
66///
67/// let mut escaped = ascii::escape_default(b'\n');
68///
69/// assert_eq!(b'\\', escaped.next().unwrap());
70/// assert_eq!(b'n', escaped.next().unwrap());
71///
72/// let mut escaped = ascii::escape_default(b'\'');
73///
74/// assert_eq!(b'\\', escaped.next().unwrap());
75/// assert_eq!(b'\'', escaped.next().unwrap());
76///
77/// let mut escaped = ascii::escape_default(b'"');
78///
79/// assert_eq!(b'\\', escaped.next().unwrap());
80/// assert_eq!(b'"', escaped.next().unwrap());
81///
82/// let mut escaped = ascii::escape_default(b'\\');
83///
84/// assert_eq!(b'\\', escaped.next().unwrap());
85/// assert_eq!(b'\\', escaped.next().unwrap());
86///
87/// let mut escaped = ascii::escape_default(b'\x9d');
88///
89/// assert_eq!(b'\\', escaped.next().unwrap());
90/// assert_eq!(b'x', escaped.next().unwrap());
91/// assert_eq!(b'9', escaped.next().unwrap());
92/// assert_eq!(b'd', escaped.next().unwrap());
93/// ```
94#[stable(feature = "rust1", since = "1.0.0")]
95#[ferrocene::prevalidated]
96pub fn escape_default(c: u8) -> EscapeDefault {
97 EscapeDefault::new(c)
98}
99
100impl EscapeDefault {
101 #[inline]
102 #[ferrocene::prevalidated]
103 pub(crate) const fn new(c: u8) -> Self {
104 Self(EscapeIterInner::ascii(c))
105 }
106
107 #[inline]
108 #[ferrocene::prevalidated]
109 pub(crate) fn empty() -> Self {
110 Self(EscapeIterInner::empty())
111 }
112}
113
114#[stable(feature = "rust1", since = "1.0.0")]
115impl Iterator for EscapeDefault {
116 type Item = u8;
117
118 #[inline]
119 #[ferrocene::prevalidated]
120 fn next(&mut self) -> Option<u8> {
121 self.0.next()
122 }
123
124 #[inline]
125 #[ferrocene::prevalidated]
126 fn size_hint(&self) -> (usize, Option<usize>) {
127 let n = self.0.len();
128 (n, Some(n))
129 }
130
131 #[inline]
132 #[ferrocene::prevalidated]
133 fn count(self) -> usize {
134 self.0.len()
135 }
136
137 #[inline]
138 #[ferrocene::prevalidated]
139 fn last(mut self) -> Option<u8> {
140 self.0.next_back()
141 }
142
143 #[inline]
144 #[ferrocene::prevalidated]
145 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
146 self.0.advance_by(n)
147 }
148}
149
150#[stable(feature = "rust1", since = "1.0.0")]
151impl DoubleEndedIterator for EscapeDefault {
152 #[inline]
153 fn next_back(&mut self) -> Option<u8> {
154 self.0.next_back()
155 }
156
157 #[inline]
158 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
159 self.0.advance_back_by(n)
160 }
161}
162
163#[stable(feature = "rust1", since = "1.0.0")]
164impl ExactSizeIterator for EscapeDefault {
165 #[inline]
166 fn len(&self) -> usize {
167 self.0.len()
168 }
169}
170
171#[stable(feature = "fused", since = "1.26.0")]
172impl FusedIterator for EscapeDefault {}
173
174#[stable(feature = "ascii_escape_display", since = "1.39.0")]
175impl fmt::Display for EscapeDefault {
176 #[ferrocene::prevalidated]
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 fmt::Display::fmt(&self.0, f)
179 }
180}
181
182#[stable(feature = "std_debug", since = "1.16.0")]
183impl fmt::Debug for EscapeDefault {
184 #[ferrocene::prevalidated]
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 f.debug_struct("EscapeDefault").finish_non_exhaustive()
187 }
188}