Skip to content

Commit 68efea0

Browse files
committed
Restore char::escape_default and add char::escape instead
1 parent 0685900 commit 68efea0

File tree

8 files changed

+145
-7
lines changed

8 files changed

+145
-7
lines changed

src/libcollections/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#![feature(allow_internal_unstable)]
3434
#![feature(box_patterns)]
3535
#![feature(box_syntax)]
36+
#![feature(char_escape)]
3637
#![feature(core_intrinsics)]
3738
#![feature(dropck_parametricity)]
3839
#![feature(fmt_internals)]

src/libcollections/str.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1697,6 +1697,14 @@ impl str {
16971697
return s;
16981698
}
16991699

1700+
/// Escapes each char in `s` with `char::escape`.
1701+
#[unstable(feature = "str_escape",
1702+
reason = "return type may change to be an iterator",
1703+
issue = "27791")]
1704+
pub fn escape(&self) -> String {
1705+
self.chars().flat_map(|c| c.escape()).collect()
1706+
}
1707+
17001708
/// Escapes each char in `s` with `char::escape_default`.
17011709
#[unstable(feature = "str_escape",
17021710
reason = "return type may change to be an iterator",

src/libcollectionstest/str.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ fn test_escape_unicode() {
704704
}
705705

706706
#[test]
707-
fn test_escape_default() {
707+
fn test_escape() {
708708
assert_eq!("abc".escape_default(), "abc");
709709
assert_eq!("a c".escape_default(), "a c");
710710
assert_eq!("éèê".escape_default(), "éèê");
@@ -717,6 +717,20 @@ fn test_escape_default() {
717717
assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
718718
}
719719

720+
#[test]
721+
fn test_escape_default() {
722+
assert_eq!("abc".escape_default(), "abc");
723+
assert_eq!("a c".escape_default(), "a c");
724+
assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
725+
assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
726+
assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
727+
assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
728+
assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
729+
assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
730+
assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
731+
assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
732+
}
733+
720734
#[test]
721735
fn test_total_ord() {
722736
assert_eq!("1234".cmp("123"), Greater);

src/libcore/char.rs

+37-1
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ pub trait CharExt {
264264
fn escape_unicode(self) -> EscapeUnicode;
265265
#[stable(feature = "core", since = "1.6.0")]
266266
fn escape_default(self) -> EscapeDefault;
267+
#[unstable(feature = "char_escape", issue = "0")]
268+
fn escape(self) -> Escape;
267269
#[stable(feature = "core", since = "1.6.0")]
268270
fn len_utf8(self) -> usize;
269271
#[stable(feature = "core", since = "1.6.0")]
@@ -316,6 +318,19 @@ impl CharExt for char {
316318

317319
#[inline]
318320
fn escape_default(self) -> EscapeDefault {
321+
let init_state = match self {
322+
'\t' => EscapeDefaultState::Backslash('t'),
323+
'\r' => EscapeDefaultState::Backslash('r'),
324+
'\n' => EscapeDefaultState::Backslash('n'),
325+
'\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
326+
'\x20' ... '\x7e' => EscapeDefaultState::Char(self),
327+
_ => EscapeDefaultState::Unicode(self.escape_unicode())
328+
};
329+
EscapeDefault { state: init_state }
330+
}
331+
332+
#[inline]
333+
fn escape(self) -> Escape {
319334
let init_state = match self {
320335
'\t' => EscapeDefaultState::Backslash('t'),
321336
'\r' => EscapeDefaultState::Backslash('r'),
@@ -324,7 +339,7 @@ impl CharExt for char {
324339
c if is_printable(c) => EscapeDefaultState::Char(c),
325340
c => EscapeDefaultState::Unicode(c.escape_unicode()),
326341
};
327-
EscapeDefault { state: init_state }
342+
Escape(EscapeDefault { state: init_state })
328343
}
329344

330345
#[inline]
@@ -601,6 +616,27 @@ impl ExactSizeIterator for EscapeDefault {
601616
}
602617
}
603618

619+
/// An iterator that yields the literal escape code of a `char`.
620+
///
621+
/// This `struct` is created by the [`escape()`] method on [`char`]. See its
622+
/// documentation for more.
623+
///
624+
/// [`escape()`]: ../../std/primitive.char.html#method.escape
625+
/// [`char`]: ../../std/primitive.char.html
626+
#[unstable(feature = "char_escape", issue = "0")]
627+
#[derive(Clone, Debug)]
628+
pub struct Escape(EscapeDefault);
629+
630+
#[unstable(feature = "char_escape", issue = "0")]
631+
impl Iterator for Escape {
632+
type Item = char;
633+
fn next(&mut self) -> Option<char> { self.0.next() }
634+
fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
635+
}
636+
637+
#[unstable(feature = "char_escape", issue = "0")]
638+
impl ExactSizeIterator for Escape { }
639+
604640
/// An iterator over `u8` entries represending the UTF-8 encoding of a `char`
605641
/// value.
606642
///

src/libcore/fmt/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1383,7 +1383,7 @@ impl Debug for str {
13831383
f.write_char('"')?;
13841384
let mut from = 0;
13851385
for (i, c) in self.char_indices() {
1386-
let esc = c.escape_default();
1386+
let esc = c.escape();
13871387
// If char needs escaping, flush backlog so far and write, else skip
13881388
if esc.len() != 1 {
13891389
f.write_str(&self[from..i])?;
@@ -1409,7 +1409,7 @@ impl Display for str {
14091409
impl Debug for char {
14101410
fn fmt(&self, f: &mut Formatter) -> Result {
14111411
f.write_char('\'')?;
1412-
for c in self.escape_default() {
1412+
for c in self.escape() {
14131413
f.write_char(c)?
14141414
}
14151415
f.write_char('\'')

src/libcoretest/char.rs

+45-2
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ fn test_is_digit() {
124124
}
125125

126126
#[test]
127-
fn test_escape_default() {
127+
fn test_escape() {
128128
fn string(c: char) -> String {
129-
c.escape_default().collect()
129+
c.escape().collect()
130130
}
131131
let s = string('\n');
132132
assert_eq!(s, "\\n");
@@ -166,6 +166,49 @@ fn test_escape_default() {
166166
assert_eq!(s, "\\u{100000}");
167167
}
168168

169+
#[test]
170+
fn test_escape_default() {
171+
fn string(c: char) -> String {
172+
c.escape_default().collect()
173+
}
174+
let s = string('\n');
175+
assert_eq!(s, "\\n");
176+
let s = string('\r');
177+
assert_eq!(s, "\\r");
178+
let s = string('\'');
179+
assert_eq!(s, "\\'");
180+
let s = string('"');
181+
assert_eq!(s, "\\\"");
182+
let s = string(' ');
183+
assert_eq!(s, " ");
184+
let s = string('a');
185+
assert_eq!(s, "a");
186+
let s = string('~');
187+
assert_eq!(s, "~");
188+
let s = string('é');
189+
assert_eq!(s, "\\u{e9}");
190+
let s = string('\x00');
191+
assert_eq!(s, "\\u{0}");
192+
let s = string('\x1f');
193+
assert_eq!(s, "\\u{1f}");
194+
let s = string('\x7f');
195+
assert_eq!(s, "\\u{7f}");
196+
let s = string('\u{80}');
197+
assert_eq!(s, "\\u{80}");
198+
let s = string('\u{ff}');
199+
assert_eq!(s, "\\u{ff}");
200+
let s = string('\u{11b}');
201+
assert_eq!(s, "\\u{11b}");
202+
let s = string('\u{1d4b6}');
203+
assert_eq!(s, "\\u{1d4b6}");
204+
let s = string('\u{200b}'); // zero width space
205+
assert_eq!(s, "\\u{200b}");
206+
let s = string('\u{e000}'); // private use 1
207+
assert_eq!(s, "\\u{e000}");
208+
let s = string('\u{100000}'); // private use 2
209+
assert_eq!(s, "\\u{100000}");
210+
}
211+
169212
#[test]
170213
fn test_escape_unicode() {
171214
fn string(c: char) -> String { c.escape_unicode().collect() }

src/librustc_unicode/char.rs

+36-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use tables::{conversions, derived_property, general_category, property};
3636
#[stable(feature = "rust1", since = "1.0.0")]
3737
pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked};
3838
#[stable(feature = "rust1", since = "1.0.0")]
39-
pub use core::char::{EncodeUtf16, EncodeUtf8, EscapeDefault, EscapeUnicode};
39+
pub use core::char::{EncodeUtf16, EncodeUtf8, Escape, EscapeDefault, EscapeUnicode};
4040

4141
// unstable reexports
4242
#[unstable(feature = "decode_utf8", issue = "33906")]
@@ -267,6 +267,41 @@ impl char {
267267
C::escape_unicode(self)
268268
}
269269

270+
/// Returns an iterator that yields the literal escape code of a `char`.
271+
///
272+
/// This will escape the characters similar to the `Debug` implementations
273+
/// of `str` or `char`.
274+
///
275+
/// # Examples
276+
///
277+
/// Basic usage:
278+
///
279+
/// ```
280+
/// for i in '\n'.escape_default() {
281+
/// println!("{}", i);
282+
/// }
283+
/// ```
284+
///
285+
/// This prints:
286+
///
287+
/// ```text
288+
/// \
289+
/// n
290+
/// ```
291+
///
292+
/// Collecting into a `String`:
293+
///
294+
/// ```
295+
/// let quote: String = '\n'.escape_default().collect();
296+
///
297+
/// assert_eq!(quote, "\\n");
298+
/// ```
299+
#[unstable(feature = "char_escape", issue = "0")]
300+
#[inline]
301+
pub fn escape(self) -> Escape {
302+
C::escape(self)
303+
}
304+
270305
/// Returns an iterator that yields the literal escape code of a `char`.
271306
///
272307
/// The default is chosen with a bias toward producing literals that are

src/librustc_unicode/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#![cfg_attr(not(stage0), deny(warnings))]
3333
#![no_std]
3434

35+
#![feature(char_escape)]
3536
#![feature(core_char_ext)]
3637
#![feature(decode_utf8)]
3738
#![feature(lang_items)]

0 commit comments

Comments
 (0)