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