2018-03-04 18:33:34 +00:00
|
|
|
//! Operations on ASCII strings and characters.
|
|
|
|
//!
|
|
|
|
//! Most string operations in Rust act on UTF-8 strings. However, at times it
|
|
|
|
//! makes more sense to only consider the ASCII character set for a specific
|
|
|
|
//! operation.
|
|
|
|
//!
|
|
|
|
//! The [`escape_default`] function provides an iterator over the bytes of an
|
|
|
|
//! escaped version of the character given.
|
|
|
|
|
2018-03-05 21:39:09 +00:00
|
|
|
#![stable(feature = "core_ascii", since = "1.26.0")]
|
2018-03-04 18:33:34 +00:00
|
|
|
|
2022-11-29 20:02:11 +00:00
|
|
|
use crate::escape;
|
2019-04-15 02:23:21 +00:00
|
|
|
use crate::fmt;
|
|
|
|
use crate::iter::FusedIterator;
|
2022-11-29 20:02:11 +00:00
|
|
|
use crate::num::NonZeroUsize;
|
2018-03-04 18:33:34 +00:00
|
|
|
|
2023-04-29 21:45:36 +00:00
|
|
|
mod ascii_char;
|
|
|
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
|
|
|
pub use ascii_char::AsciiChar as Char;
|
|
|
|
|
2018-03-04 18:33:34 +00:00
|
|
|
/// An iterator over the escaped version of a byte.
|
|
|
|
///
|
|
|
|
/// This `struct` is created by the [`escape_default`] function. See its
|
|
|
|
/// documentation for more.
|
2021-10-14 22:54:55 +00:00
|
|
|
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
2018-04-04 23:35:09 +00:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2019-08-09 18:58:09 +00:00
|
|
|
#[derive(Clone)]
|
2022-11-29 20:02:11 +00:00
|
|
|
pub struct EscapeDefault(escape::EscapeIterInner<4>);
|
2018-03-04 18:33:34 +00:00
|
|
|
|
|
|
|
/// Returns an iterator that produces an escaped version of a `u8`.
|
|
|
|
///
|
|
|
|
/// The default is chosen with a bias toward producing literals that are
|
|
|
|
/// legal in a variety of languages, including C++11 and similar C-family
|
|
|
|
/// languages. The exact rules are:
|
|
|
|
///
|
|
|
|
/// * Tab is escaped as `\t`.
|
|
|
|
/// * Carriage return is escaped as `\r`.
|
|
|
|
/// * Line feed is escaped as `\n`.
|
|
|
|
/// * Single quote is escaped as `\'`.
|
|
|
|
/// * Double quote is escaped as `\"`.
|
|
|
|
/// * Backslash is escaped as `\\`.
|
|
|
|
/// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
|
|
|
|
/// inclusive is not escaped.
|
|
|
|
/// * Any other chars are given hex escapes of the form '\xNN'.
|
|
|
|
/// * Unicode escapes are never generated by this function.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2018-03-05 01:32:44 +00:00
|
|
|
/// use std::ascii;
|
2018-03-04 19:39:14 +00:00
|
|
|
///
|
2018-03-04 18:33:34 +00:00
|
|
|
/// let escaped = ascii::escape_default(b'0').next().unwrap();
|
|
|
|
/// assert_eq!(b'0', escaped);
|
|
|
|
///
|
|
|
|
/// let mut escaped = ascii::escape_default(b'\t');
|
|
|
|
///
|
|
|
|
/// assert_eq!(b'\\', escaped.next().unwrap());
|
|
|
|
/// assert_eq!(b't', escaped.next().unwrap());
|
|
|
|
///
|
|
|
|
/// let mut escaped = ascii::escape_default(b'\r');
|
|
|
|
///
|
|
|
|
/// assert_eq!(b'\\', escaped.next().unwrap());
|
|
|
|
/// assert_eq!(b'r', escaped.next().unwrap());
|
|
|
|
///
|
|
|
|
/// let mut escaped = ascii::escape_default(b'\n');
|
|
|
|
///
|
|
|
|
/// assert_eq!(b'\\', escaped.next().unwrap());
|
|
|
|
/// assert_eq!(b'n', escaped.next().unwrap());
|
|
|
|
///
|
|
|
|
/// let mut escaped = ascii::escape_default(b'\'');
|
|
|
|
///
|
|
|
|
/// assert_eq!(b'\\', escaped.next().unwrap());
|
|
|
|
/// assert_eq!(b'\'', escaped.next().unwrap());
|
|
|
|
///
|
|
|
|
/// let mut escaped = ascii::escape_default(b'"');
|
|
|
|
///
|
|
|
|
/// assert_eq!(b'\\', escaped.next().unwrap());
|
|
|
|
/// assert_eq!(b'"', escaped.next().unwrap());
|
|
|
|
///
|
|
|
|
/// let mut escaped = ascii::escape_default(b'\\');
|
|
|
|
///
|
|
|
|
/// assert_eq!(b'\\', escaped.next().unwrap());
|
|
|
|
/// assert_eq!(b'\\', escaped.next().unwrap());
|
|
|
|
///
|
|
|
|
/// let mut escaped = ascii::escape_default(b'\x9d');
|
|
|
|
///
|
|
|
|
/// assert_eq!(b'\\', escaped.next().unwrap());
|
|
|
|
/// assert_eq!(b'x', escaped.next().unwrap());
|
|
|
|
/// assert_eq!(b'9', escaped.next().unwrap());
|
|
|
|
/// assert_eq!(b'd', escaped.next().unwrap());
|
|
|
|
/// ```
|
2018-04-04 23:35:09 +00:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2018-03-04 19:39:14 +00:00
|
|
|
pub fn escape_default(c: u8) -> EscapeDefault {
|
2022-11-29 20:02:11 +00:00
|
|
|
let mut data = [0; 4];
|
|
|
|
let range = escape::escape_ascii_into(&mut data, c);
|
|
|
|
EscapeDefault(escape::EscapeIterInner::new(data, range))
|
2018-03-04 18:33:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
impl Iterator for EscapeDefault {
|
|
|
|
type Item = u8;
|
2022-03-10 14:35:22 +00:00
|
|
|
|
|
|
|
#[inline]
|
2018-03-04 18:33:34 +00:00
|
|
|
fn next(&mut self) -> Option<u8> {
|
2022-11-29 20:02:11 +00:00
|
|
|
self.0.next()
|
2018-03-04 18:33:34 +00:00
|
|
|
}
|
2022-11-29 20:02:11 +00:00
|
|
|
|
|
|
|
#[inline]
|
2018-03-04 18:33:34 +00:00
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
2022-11-29 20:02:11 +00:00
|
|
|
let n = self.0.len();
|
|
|
|
(n, Some(n))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn count(self) -> usize {
|
|
|
|
self.0.len()
|
2018-03-04 18:33:34 +00:00
|
|
|
}
|
2022-11-29 20:02:11 +00:00
|
|
|
|
|
|
|
#[inline]
|
When possible without changing semantics, implement Iterator::last in terms of DoubleEndedIterator::next_back for types in liballoc and libcore.
Provided that the iterator has finite length and does not trigger user-provided code, this is safe.
What follows is a full list of the DoubleEndedIterators in liballoc/libcore and whether this optimization is safe, and if not, why not.
src/liballoc/boxed.rs
Box: Pass through to avoid defeating optimization of the underlying DoubleIterator implementation. This has no correctness impact.
src/liballoc/collections/binary_heap.rs
Iter: Pass through to avoid defeating optimizations on slice::Iter
IntoIter: Not safe, changes Drop order
Drain: Not safe, changes Drop order
src/liballoc/collections/btree/map.rs
Iter: Safe to call next_back, invokes no user defined code.
IterMut: ditto
IntoIter: Not safe, changes Drop order
Keys: Safe to call next_back, invokes no user defined code.
Values: ditto
ValuesMut: ditto
Range: ditto
RangeMut: ditto
src/liballoc/collections/btree/set.rs
Iter: Safe to call next_back, invokes no user defined code.
IntoIter: Not safe, changes Drop order
Range: Safe to call next_back, invokes no user defined code.
src/liballoc/collections/linked_list.rs
Iter: Safe to call next_back, invokes no user defined code.
IterMut: ditto
IntoIter: Not safe, changes Drop order
src/liballoc/collections/vec_deque.rs
Iter: Safe to call next_back, invokes no user defined code.
IterMut: ditto
IntoIter: Not safe, changes Drop order
Drain: ditto
src/liballoc/string.rs
Drain: Safe because return type is a primitive (char)
src/liballoc/vec.rs
IntoIter: Not safe, changes Drop order
Drain: ditto
Splice: ditto
src/libcore/ascii.rs
EscapeDefault: Safe because return type is a primitive (u8)
src/libcore/iter/adapters/chain.rs
Chain: Not safe, invokes user defined code (Iterator impl)
src/libcore/iter/adapters/flatten.rs
FlatMap: Not safe, invokes user defined code (Iterator impl)
Flatten: ditto
FlattenCompat: ditto
src/libcore/iter/adapters/mod.rs
Rev: Not safe, invokes user defined code (Iterator impl)
Copied: ditto
Cloned: Not safe, invokes user defined code (Iterator impl and T::clone)
Map: Not safe, invokes user defined code (Iterator impl + closure)
Filter: ditto
FilterMap: ditto
Enumerate: Not safe, invokes user defined code (Iterator impl)
Skip: ditto
Fuse: ditto
Inspect: ditto
src/libcore/iter/adapters/zip.rs
Zip: Not safe, invokes user defined code (Iterator impl)
src/libcore/iter/range.rs
ops::Range: Not safe, changes Drop order, but ALREADY HAS SPECIALIZATION
ops::RangeInclusive: ditto
src/libcore/iter/sources.rs
Repeat: Not safe, calling last should iloop.
Empty: No point, iterator is at most one item long.
Once: ditto
OnceWith: ditto
src/libcore/option.rs
Item: No point, iterator is at most one item long.
Iter: ditto
IterMut: ditto
IntoIter: ditto
src/libcore/result.rs
Iter: No point, iterator is at most one item long
IterMut: ditto
IntoIter: ditto
src/libcore/slice/mod.rs
Split: Not safe, invokes user defined closure
SplitMut: ditto
RSplit: ditto
RSplitMut: ditto
Windows: Safe, already has specialization
Chunks: ditto
ChunksMut: ditto
ChunksExact: ditto
ChunksExactMut: ditto
RChunks: ditto
RChunksMut: ditto
RChunksExact: ditto
RChunksExactMut: ditto
src/libcore/str/mod.rs
Chars: Safe, already has specialization
CharIndices: ditto
Bytes: ditto
Lines: Safe to call next_back, invokes no user defined code.
LinesAny: Deprecated
Everything that is generic over P: Pattern: Not safe because Pattern invokes user defined code.
SplitWhitespace: Safe to call next_back, invokes no user defined code.
SplitAsciiWhitespace: ditto
2019-07-02 20:45:29 +00:00
|
|
|
fn last(mut self) -> Option<u8> {
|
2022-11-29 20:02:11 +00:00
|
|
|
self.0.next_back()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
|
|
|
self.0.advance_by(n)
|
When possible without changing semantics, implement Iterator::last in terms of DoubleEndedIterator::next_back for types in liballoc and libcore.
Provided that the iterator has finite length and does not trigger user-provided code, this is safe.
What follows is a full list of the DoubleEndedIterators in liballoc/libcore and whether this optimization is safe, and if not, why not.
src/liballoc/boxed.rs
Box: Pass through to avoid defeating optimization of the underlying DoubleIterator implementation. This has no correctness impact.
src/liballoc/collections/binary_heap.rs
Iter: Pass through to avoid defeating optimizations on slice::Iter
IntoIter: Not safe, changes Drop order
Drain: Not safe, changes Drop order
src/liballoc/collections/btree/map.rs
Iter: Safe to call next_back, invokes no user defined code.
IterMut: ditto
IntoIter: Not safe, changes Drop order
Keys: Safe to call next_back, invokes no user defined code.
Values: ditto
ValuesMut: ditto
Range: ditto
RangeMut: ditto
src/liballoc/collections/btree/set.rs
Iter: Safe to call next_back, invokes no user defined code.
IntoIter: Not safe, changes Drop order
Range: Safe to call next_back, invokes no user defined code.
src/liballoc/collections/linked_list.rs
Iter: Safe to call next_back, invokes no user defined code.
IterMut: ditto
IntoIter: Not safe, changes Drop order
src/liballoc/collections/vec_deque.rs
Iter: Safe to call next_back, invokes no user defined code.
IterMut: ditto
IntoIter: Not safe, changes Drop order
Drain: ditto
src/liballoc/string.rs
Drain: Safe because return type is a primitive (char)
src/liballoc/vec.rs
IntoIter: Not safe, changes Drop order
Drain: ditto
Splice: ditto
src/libcore/ascii.rs
EscapeDefault: Safe because return type is a primitive (u8)
src/libcore/iter/adapters/chain.rs
Chain: Not safe, invokes user defined code (Iterator impl)
src/libcore/iter/adapters/flatten.rs
FlatMap: Not safe, invokes user defined code (Iterator impl)
Flatten: ditto
FlattenCompat: ditto
src/libcore/iter/adapters/mod.rs
Rev: Not safe, invokes user defined code (Iterator impl)
Copied: ditto
Cloned: Not safe, invokes user defined code (Iterator impl and T::clone)
Map: Not safe, invokes user defined code (Iterator impl + closure)
Filter: ditto
FilterMap: ditto
Enumerate: Not safe, invokes user defined code (Iterator impl)
Skip: ditto
Fuse: ditto
Inspect: ditto
src/libcore/iter/adapters/zip.rs
Zip: Not safe, invokes user defined code (Iterator impl)
src/libcore/iter/range.rs
ops::Range: Not safe, changes Drop order, but ALREADY HAS SPECIALIZATION
ops::RangeInclusive: ditto
src/libcore/iter/sources.rs
Repeat: Not safe, calling last should iloop.
Empty: No point, iterator is at most one item long.
Once: ditto
OnceWith: ditto
src/libcore/option.rs
Item: No point, iterator is at most one item long.
Iter: ditto
IterMut: ditto
IntoIter: ditto
src/libcore/result.rs
Iter: No point, iterator is at most one item long
IterMut: ditto
IntoIter: ditto
src/libcore/slice/mod.rs
Split: Not safe, invokes user defined closure
SplitMut: ditto
RSplit: ditto
RSplitMut: ditto
Windows: Safe, already has specialization
Chunks: ditto
ChunksMut: ditto
ChunksExact: ditto
ChunksExactMut: ditto
RChunks: ditto
RChunksMut: ditto
RChunksExact: ditto
RChunksExactMut: ditto
src/libcore/str/mod.rs
Chars: Safe, already has specialization
CharIndices: ditto
Bytes: ditto
Lines: Safe to call next_back, invokes no user defined code.
LinesAny: Deprecated
Everything that is generic over P: Pattern: Not safe because Pattern invokes user defined code.
SplitWhitespace: Safe to call next_back, invokes no user defined code.
SplitAsciiWhitespace: ditto
2019-07-02 20:45:29 +00:00
|
|
|
}
|
2018-03-04 18:33:34 +00:00
|
|
|
}
|
2022-11-29 20:02:11 +00:00
|
|
|
|
2018-03-04 18:33:34 +00:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
impl DoubleEndedIterator for EscapeDefault {
|
2022-11-29 20:02:11 +00:00
|
|
|
#[inline]
|
2018-03-04 18:33:34 +00:00
|
|
|
fn next_back(&mut self) -> Option<u8> {
|
2022-11-29 20:02:11 +00:00
|
|
|
self.0.next_back()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
|
|
|
self.0.advance_back_by(n)
|
2018-03-04 18:33:34 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-29 20:02:11 +00:00
|
|
|
|
2018-03-04 18:33:34 +00:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2022-11-29 20:02:11 +00:00
|
|
|
impl ExactSizeIterator for EscapeDefault {
|
|
|
|
#[inline]
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
self.0.len()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-06 21:33:38 +00:00
|
|
|
#[stable(feature = "fused", since = "1.26.0")]
|
2018-03-04 18:33:34 +00:00
|
|
|
impl FusedIterator for EscapeDefault {}
|
|
|
|
|
2019-08-09 18:58:09 +00:00
|
|
|
#[stable(feature = "ascii_escape_display", since = "1.39.0")]
|
|
|
|
impl fmt::Display for EscapeDefault {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2022-11-29 20:02:11 +00:00
|
|
|
f.write_str(self.0.as_str())
|
2019-08-09 18:58:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-04 18:33:34 +00:00
|
|
|
#[stable(feature = "std_debug", since = "1.16.0")]
|
|
|
|
impl fmt::Debug for EscapeDefault {
|
2019-04-18 23:37:12 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-04-05 11:31:11 +00:00
|
|
|
f.debug_struct("EscapeDefault").finish_non_exhaustive()
|
2018-03-04 18:33:34 +00:00
|
|
|
}
|
|
|
|
}
|