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;
14#[cfg(not(feature = "ferrocene_subset"))]
15use crate::iter::FusedIterator;
16use crate::num::NonZero;
17
18mod ascii_char;
19#[doc(alias("AsciiChar"))]
20#[unstable(feature = "ascii_char", issue = "110998")]
21pub use ascii_char::AsciiChar as Char;
22
23/// An iterator over the escaped version of a byte.
24///
25/// This `struct` is created by the [`escape_default`] function. See its
26/// documentation for more.
27#[must_use = "iterators are lazy and do nothing unless consumed"]
28#[stable(feature = "rust1", since = "1.0.0")]
29#[derive(Clone)]
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")]
95pub fn escape_default(c: u8) -> EscapeDefault {
96 EscapeDefault::new(c)
97}
98
99impl EscapeDefault {
100 #[inline]
101 pub(crate) const fn new(c: u8) -> Self {
102 Self(EscapeIterInner::ascii(c))
103 }
104
105 #[inline]
106 pub(crate) fn empty() -> Self {
107 Self(EscapeIterInner::empty())
108 }
109}
110
111#[stable(feature = "rust1", since = "1.0.0")]
112impl Iterator for EscapeDefault {
113 type Item = u8;
114
115 #[inline]
116 fn next(&mut self) -> Option<u8> {
117 self.0.next()
118 }
119
120 #[inline]
121 fn size_hint(&self) -> (usize, Option<usize>) {
122 let n = self.0.len();
123 (n, Some(n))
124 }
125
126 #[inline]
127 fn count(self) -> usize {
128 self.0.len()
129 }
130
131 #[inline]
132 fn last(mut self) -> Option<u8> {
133 self.0.next_back()
134 }
135
136 #[inline]
137 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
138 self.0.advance_by(n)
139 }
140}
141
142#[stable(feature = "rust1", since = "1.0.0")]
143#[cfg(not(feature = "ferrocene_subset"))]
144impl DoubleEndedIterator for EscapeDefault {
145 #[inline]
146 fn next_back(&mut self) -> Option<u8> {
147 self.0.next_back()
148 }
149
150 #[inline]
151 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
152 self.0.advance_back_by(n)
153 }
154}
155
156#[stable(feature = "rust1", since = "1.0.0")]
157#[cfg(not(feature = "ferrocene_subset"))]
158impl ExactSizeIterator for EscapeDefault {
159 #[inline]
160 fn len(&self) -> usize {
161 self.0.len()
162 }
163}
164
165#[stable(feature = "fused", since = "1.26.0")]
166#[cfg(not(feature = "ferrocene_subset"))]
167impl FusedIterator for EscapeDefault {}
168
169#[stable(feature = "ascii_escape_display", since = "1.39.0")]
170impl fmt::Display for EscapeDefault {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 fmt::Display::fmt(&self.0, f)
173 }
174}
175
176#[stable(feature = "std_debug", since = "1.16.0")]
177impl fmt::Debug for EscapeDefault {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 f.debug_struct("EscapeDefault").finish_non_exhaustive()
180 }
181}