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