Skip to main content

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}