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}