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)]
29pub struct EscapeDefault(EscapeIterInner<4, AlwaysEscaped>);
30
31/// Returns an iterator that produces an escaped version of a `u8`.
32///
33/// The default is chosen with a bias toward producing literals that are
34/// legal in a variety of languages, including C++11 and similar C-family
35/// languages. The exact rules are:
36///
37/// * Tab is escaped as `\t`.
38/// * Carriage return is escaped as `\r`.
39/// * Line feed is escaped as `\n`.
40/// * Single quote is escaped as `\'`.
41/// * Double quote is escaped as `\"`.
42/// * Backslash is escaped as `\\`.
43/// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
44///   inclusive is not escaped.
45/// * Any other chars are given hex escapes of the form '\xNN'.
46/// * Unicode escapes are never generated by this function.
47///
48/// # Examples
49///
50/// ```
51/// use std::ascii;
52///
53/// let escaped = ascii::escape_default(b'0').next().unwrap();
54/// assert_eq!(b'0', escaped);
55///
56/// let mut escaped = ascii::escape_default(b'\t');
57///
58/// assert_eq!(b'\\', escaped.next().unwrap());
59/// assert_eq!(b't', escaped.next().unwrap());
60///
61/// let mut escaped = ascii::escape_default(b'\r');
62///
63/// assert_eq!(b'\\', escaped.next().unwrap());
64/// assert_eq!(b'r', escaped.next().unwrap());
65///
66/// let mut escaped = ascii::escape_default(b'\n');
67///
68/// assert_eq!(b'\\', escaped.next().unwrap());
69/// assert_eq!(b'n', escaped.next().unwrap());
70///
71/// let mut escaped = ascii::escape_default(b'\'');
72///
73/// assert_eq!(b'\\', escaped.next().unwrap());
74/// assert_eq!(b'\'', escaped.next().unwrap());
75///
76/// let mut escaped = ascii::escape_default(b'"');
77///
78/// assert_eq!(b'\\', escaped.next().unwrap());
79/// assert_eq!(b'"', escaped.next().unwrap());
80///
81/// let mut escaped = ascii::escape_default(b'\\');
82///
83/// assert_eq!(b'\\', escaped.next().unwrap());
84/// assert_eq!(b'\\', escaped.next().unwrap());
85///
86/// let mut escaped = ascii::escape_default(b'\x9d');
87///
88/// assert_eq!(b'\\', escaped.next().unwrap());
89/// assert_eq!(b'x', escaped.next().unwrap());
90/// assert_eq!(b'9', escaped.next().unwrap());
91/// assert_eq!(b'd', escaped.next().unwrap());
92/// ```
93#[stable(feature = "rust1", since = "1.0.0")]
94pub fn escape_default(c: u8) -> EscapeDefault {
95    EscapeDefault::new(c)
96}
97
98impl EscapeDefault {
99    #[inline]
100    pub(crate) const fn new(c: u8) -> Self {
101        Self(EscapeIterInner::ascii(c))
102    }
103
104    #[inline]
105    pub(crate) fn empty() -> Self {
106        Self(EscapeIterInner::empty())
107    }
108}
109
110#[stable(feature = "rust1", since = "1.0.0")]
111impl 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<(), NonZero<usize>> {
137        self.0.advance_by(n)
138    }
139}
140
141#[stable(feature = "rust1", since = "1.0.0")]
142impl 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<(), NonZero<usize>> {
150        self.0.advance_back_by(n)
151    }
152}
153
154#[stable(feature = "rust1", since = "1.0.0")]
155impl 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")]
163impl FusedIterator for EscapeDefault {}
164
165#[stable(feature = "ascii_escape_display", since = "1.39.0")]
166impl fmt::Display for EscapeDefault {
167    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168        fmt::Display::fmt(&self.0, f)
169    }
170}
171
172#[stable(feature = "std_debug", since = "1.16.0")]
173impl fmt::Debug for EscapeDefault {
174    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175        f.debug_struct("EscapeDefault").finish_non_exhaustive()
176    }
177}