Implement Display for char Escape*, To*case.

This commit is contained in:
Clar Charr 2017-01-07 13:16:03 -05:00
parent 0500fbf6ba
commit 3a79f2e2f1
3 changed files with 284 additions and 182 deletions

View file

@ -17,7 +17,7 @@
use char_private::is_printable;
use convert::TryFrom;
use fmt;
use fmt::{self, Write};
use slice;
use iter::FusedIterator;
use mem::transmute;
@ -588,6 +588,16 @@ impl ExactSizeIterator for EscapeUnicode {
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EscapeUnicode {}
#[stable(feature = "char_struct_display", since = "1.17.0")]
impl fmt::Display for EscapeUnicode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for c in self.clone() {
f.write_char(c)?;
}
Ok(())
}
}
/// An iterator that yields the literal escape code of a `char`.
///
/// This `struct` is created by the [`escape_default()`] method on [`char`]. See
@ -691,6 +701,16 @@ impl ExactSizeIterator for EscapeDefault {
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EscapeDefault {}
#[stable(feature = "char_struct_display", since = "1.17.0")]
impl fmt::Display for EscapeDefault {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for c in self.clone() {
f.write_char(c)?;
}
Ok(())
}
}
/// An iterator that yields the literal escape code of a `char`.
///
/// This `struct` is created by the [`escape_debug()`] method on [`char`]. See its
@ -715,6 +735,13 @@ impl ExactSizeIterator for EscapeDebug { }
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EscapeDebug {}
#[stable(feature = "char_struct_display", since = "1.17.0")]
impl fmt::Display for EscapeDebug {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
/// An iterator over an iterator of bytes of the characters the bytes represent

View file

@ -75,47 +75,53 @@ fn test_to_digit() {
#[test]
fn test_to_lowercase() {
fn lower(c: char) -> Vec<char> {
c.to_lowercase().collect()
fn lower(c: char) -> String {
let iter: String = c.to_lowercase().collect();
let disp: String = c.to_lowercase().to_string();
assert_eq!(iter, disp);
iter
}
assert_eq!(lower('A'), ['a']);
assert_eq!(lower('Ö'), ['ö']);
assert_eq!(lower('ß'), ['ß']);
assert_eq!(lower('Ü'), ['ü']);
assert_eq!(lower('💩'), ['💩']);
assert_eq!(lower('Σ'), ['σ']);
assert_eq!(lower('Τ'), ['τ']);
assert_eq!(lower('Ι'), ['ι']);
assert_eq!(lower('Γ'), ['γ']);
assert_eq!(lower('Μ'), ['μ']);
assert_eq!(lower('Α'), ['α']);
assert_eq!(lower('Σ'), ['σ']);
assert_eq!(lower('Dž'), ['dž']);
assert_eq!(lower('fi'), ['fi']);
assert_eq!(lower('İ'), ['i', '\u{307}']);
assert_eq!(lower('A'), "a");
assert_eq!(lower('Ö'), "ö");
assert_eq!(lower('ß'), "ß");
assert_eq!(lower('Ü'), "ü");
assert_eq!(lower('💩'), "💩");
assert_eq!(lower('Σ'), "σ");
assert_eq!(lower('Τ'), "τ");
assert_eq!(lower('Ι'), "ι");
assert_eq!(lower('Γ'), "γ");
assert_eq!(lower('Μ'), "μ");
assert_eq!(lower('Α'), "α");
assert_eq!(lower('Σ'), "σ");
assert_eq!(lower('Dž'), "dž");
assert_eq!(lower('fi'), "");
assert_eq!(lower('İ'), "i\u{307}");
}
#[test]
fn test_to_uppercase() {
fn upper(c: char) -> Vec<char> {
c.to_uppercase().collect()
fn upper(c: char) -> String {
let iter: String = c.to_uppercase().collect();
let disp: String = c.to_uppercase().to_string();
assert_eq!(iter, disp);
iter
}
assert_eq!(upper('a'), ['A']);
assert_eq!(upper('ö'), ['Ö']);
assert_eq!(upper('ß'), ['S', 'S']); // not ẞ: Latin capital letter sharp s
assert_eq!(upper('ü'), ['Ü']);
assert_eq!(upper('💩'), ['💩']);
assert_eq!(upper('a'), "A");
assert_eq!(upper('ö'), "Ö");
assert_eq!(upper('ß'), "SS"); // not ẞ: Latin capital letter sharp s
assert_eq!(upper('ü'), "Ü");
assert_eq!(upper('💩'), "💩");
assert_eq!(upper('σ'), ['Σ']);
assert_eq!(upper('τ'), ['Τ']);
assert_eq!(upper('ι'), ['Ι']);
assert_eq!(upper('γ'), ['Γ']);
assert_eq!(upper('μ'), ['Μ']);
assert_eq!(upper('α'), ['Α']);
assert_eq!(upper('ς'), ['Σ']);
assert_eq!(upper('Dž'), ['DŽ']);
assert_eq!(upper('fi'), ['F', 'I']);
assert_eq!(upper('ᾀ'), ['Ἀ', 'Ι']);
assert_eq!(upper('σ'), "Σ");
assert_eq!(upper('τ'), "Τ");
assert_eq!(upper('ι'), "Ι");
assert_eq!(upper('γ'), "Γ");
assert_eq!(upper('μ'), "Μ");
assert_eq!(upper('α'), "Α");
assert_eq!(upper('ς'), "Σ");
assert_eq!(upper('Dž'), "DŽ");
assert_eq!(upper('fi'), "FI");
assert_eq!(upper('ᾀ'), "ἈΙ");
}
#[test]
@ -144,107 +150,75 @@ fn test_is_digit() {
#[test]
fn test_escape_debug() {
fn string(c: char) -> String {
c.escape_debug().collect()
let iter: String = c.escape_debug().collect();
let disp: String = c.escape_debug().to_string();
assert_eq!(iter, disp);
iter
}
let s = string('\n');
assert_eq!(s, "\\n");
let s = string('\r');
assert_eq!(s, "\\r");
let s = string('\'');
assert_eq!(s, "\\'");
let s = string('"');
assert_eq!(s, "\\\"");
let s = string(' ');
assert_eq!(s, " ");
let s = string('a');
assert_eq!(s, "a");
let s = string('~');
assert_eq!(s, "~");
let s = string('é');
assert_eq!(s, "é");
let s = string('文');
assert_eq!(s, "");
let s = string('\x00');
assert_eq!(s, "\\u{0}");
let s = string('\x1f');
assert_eq!(s, "\\u{1f}");
let s = string('\x7f');
assert_eq!(s, "\\u{7f}");
let s = string('\u{80}');
assert_eq!(s, "\\u{80}");
let s = string('\u{ff}');
assert_eq!(s, "\u{ff}");
let s = string('\u{11b}');
assert_eq!(s, "\u{11b}");
let s = string('\u{1d4b6}');
assert_eq!(s, "\u{1d4b6}");
let s = string('\u{200b}'); // zero width space
assert_eq!(s, "\\u{200b}");
let s = string('\u{e000}'); // private use 1
assert_eq!(s, "\\u{e000}");
let s = string('\u{100000}'); // private use 2
assert_eq!(s, "\\u{100000}");
assert_eq!(string('\n'), "\\n");
assert_eq!(string('\r'), "\\r");
assert_eq!(string('\''), "\\'");
assert_eq!(string('"'), "\\\"");
assert_eq!(string(' '), " ");
assert_eq!(string('a'), "a");
assert_eq!(string('~'), "~");
assert_eq!(string('é'), "é");
assert_eq!(string('文'), "");
assert_eq!(string('\x00'), "\\u{0}");
assert_eq!(string('\x1f'), "\\u{1f}");
assert_eq!(string('\x7f'), "\\u{7f}");
assert_eq!(string('\u{80}'), "\\u{80}");
assert_eq!(string('\u{ff}'), "\u{ff}");
assert_eq!(string('\u{11b}'), "\u{11b}");
assert_eq!(string('\u{1d4b6}'), "\u{1d4b6}");
assert_eq!(string('\u{200b}'),"\\u{200b}"); // zero width space
assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1
assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
}
#[test]
fn test_escape_default() {
fn string(c: char) -> String {
c.escape_default().collect()
let iter: String = c.escape_default().collect();
let disp: String = c.escape_default().to_string();
assert_eq!(iter, disp);
iter
}
let s = string('\n');
assert_eq!(s, "\\n");
let s = string('\r');
assert_eq!(s, "\\r");
let s = string('\'');
assert_eq!(s, "\\'");
let s = string('"');
assert_eq!(s, "\\\"");
let s = string(' ');
assert_eq!(s, " ");
let s = string('a');
assert_eq!(s, "a");
let s = string('~');
assert_eq!(s, "~");
let s = string('é');
assert_eq!(s, "\\u{e9}");
let s = string('\x00');
assert_eq!(s, "\\u{0}");
let s = string('\x1f');
assert_eq!(s, "\\u{1f}");
let s = string('\x7f');
assert_eq!(s, "\\u{7f}");
let s = string('\u{80}');
assert_eq!(s, "\\u{80}");
let s = string('\u{ff}');
assert_eq!(s, "\\u{ff}");
let s = string('\u{11b}');
assert_eq!(s, "\\u{11b}");
let s = string('\u{1d4b6}');
assert_eq!(s, "\\u{1d4b6}");
let s = string('\u{200b}'); // zero width space
assert_eq!(s, "\\u{200b}");
let s = string('\u{e000}'); // private use 1
assert_eq!(s, "\\u{e000}");
let s = string('\u{100000}'); // private use 2
assert_eq!(s, "\\u{100000}");
assert_eq!(string('\n'), "\\n");
assert_eq!(string('\r'), "\\r");
assert_eq!(string('\''), "\\'");
assert_eq!(string('"'), "\\\"");
assert_eq!(string(' '), " ");
assert_eq!(string('a'), "a");
assert_eq!(string('~'), "~");
assert_eq!(string('é'), "\\u{e9}");
assert_eq!(string('\x00'), "\\u{0}");
assert_eq!(string('\x1f'), "\\u{1f}");
assert_eq!(string('\x7f'), "\\u{7f}");
assert_eq!(string('\u{80}'), "\\u{80}");
assert_eq!(string('\u{ff}'), "\\u{ff}");
assert_eq!(string('\u{11b}'), "\\u{11b}");
assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}");
assert_eq!(string('\u{200b}'), "\\u{200b}"); // zero width space
assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1
assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
}
#[test]
fn test_escape_unicode() {
fn string(c: char) -> String { c.escape_unicode().collect() }
fn string(c: char) -> String {
let iter: String = c.escape_unicode().collect();
let disp: String = c.escape_unicode().to_string();
assert_eq!(iter, disp);
iter
}
let s = string('\x00');
assert_eq!(s, "\\u{0}");
let s = string('\n');
assert_eq!(s, "\\u{a}");
let s = string(' ');
assert_eq!(s, "\\u{20}");
let s = string('a');
assert_eq!(s, "\\u{61}");
let s = string('\u{11b}');
assert_eq!(s, "\\u{11b}");
let s = string('\u{1d4b6}');
assert_eq!(s, "\\u{1d4b6}");
assert_eq!(string('\x00'), "\\u{0}");
assert_eq!(string('\n'), "\\u{a}");
assert_eq!(string(' '), "\\u{20}");
assert_eq!(string('a'), "\\u{61}");
assert_eq!(string('\u{11b}'), "\\u{11b}");
assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}");
}
#[test]

View file

@ -30,7 +30,7 @@
use core::char::CharExt as C;
use core::iter::FusedIterator;
use core::fmt;
use core::fmt::{self, Write};
use tables::{conversions, derived_property, general_category, property};
// stable reexports
@ -131,6 +131,41 @@ impl Iterator for CaseMappingIter {
}
}
#[stable(feature = "char_struct_display", since = "1.17.0")]
impl fmt::Display for CaseMappingIter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CaseMappingIter::Three(a, b, c) => {
f.write_char(a)?;
f.write_char(b)?;
f.write_char(c)
}
CaseMappingIter::Two(b, c) => {
f.write_char(b)?;
f.write_char(c)
}
CaseMappingIter::One(c) => {
f.write_char(c)
}
CaseMappingIter::Zero => Ok(()),
}
}
}
#[stable(feature = "char_struct_display", since = "1.17.0")]
impl fmt::Display for ToLowercase {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
#[stable(feature = "char_struct_display", since = "1.17.0")]
impl fmt::Display for ToUppercase {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
#[lang = "char"]
impl char {
/// Checks if a `char` is a digit in the given radix.
@ -240,34 +275,38 @@ impl char {
}
/// Returns an iterator that yields the hexadecimal Unicode escape of a
/// character, as `char`s.
/// character as `char`s.
///
/// All characters are escaped with Rust syntax of the form `\u{NNNNNN}`
/// where `NNNNNN` is the shortest hexadecimal representation.
/// This will escape characters with the Rust syntax of the form
/// `\u{NNNNNN}` where `NNNNNN` is a hexadecimal representation.
///
/// # Examples
///
/// Basic usage:
/// As an iterator:
///
/// ```
/// for c in '❤'.escape_unicode() {
/// print!("{}", c);
/// }
/// println!("");
/// println!();
/// ```
///
/// This prints:
///
/// ```text
/// \u{2764}
/// ```
///
/// Collecting into a `String`:
/// Using `println!` directly:
///
/// ```
/// let heart: String = '❤'.escape_unicode().collect();
/// println!("{}", '❤'.escape_unicode());
/// ```
///
/// assert_eq!(heart, r"\u{2764}");
/// Both are equivalent to:
///
/// ```
/// println!("\\u{{2764}}");
/// ```
///
/// Using `to_string`:
///
/// ```
/// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
@ -275,34 +314,42 @@ impl char {
C::escape_unicode(self)
}
/// Returns an iterator that yields the literal escape code of a `char`.
/// Returns an iterator that yields the literal escape code of a character
/// as `char`s.
///
/// This will escape the characters similar to the `Debug` implementations
/// of `str` or `char`.
///
/// # Examples
///
/// Basic usage:
/// As an iterator:
///
/// ```
/// for i in '\n'.escape_default() {
/// println!("{}", i);
/// # #![feature(char_escape_debug)]
/// for c in '\n'.escape_debug() {
/// print!("{}", c);
/// }
/// println!();
/// ```
///
/// This prints:
///
/// ```text
/// \
/// n
/// ```
///
/// Collecting into a `String`:
/// Using `println!` directly:
///
/// ```
/// let quote: String = '\n'.escape_default().collect();
/// # #![feature(char_escape_debug)]
/// println!("{}", '\n'.escape_debug());
/// ```
///
/// assert_eq!(quote, "\\n");
/// Both are equivalent to:
///
/// ```
/// println!("\\n");
/// ```
///
/// Using `to_string`:
///
/// ```
/// # #![feature(char_escape_debug)]
/// assert_eq!('\n'.escape_debug().to_string(), "\\n");
/// ```
#[unstable(feature = "char_escape_debug", issue = "35068")]
#[inline]
@ -310,7 +357,8 @@ impl char {
C::escape_debug(self)
}
/// Returns an iterator that yields the literal escape code of a `char`.
/// Returns an iterator that yields the literal escape code of a character
/// as `char`s.
///
/// 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
@ -331,27 +379,32 @@ impl char {
///
/// # Examples
///
/// Basic usage:
/// As an iterator:
///
/// ```
/// for i in '"'.escape_default() {
/// println!("{}", i);
/// for c in '"'.escape_default() {
/// print!("{}", c);
/// }
/// println!();
/// ```
///
/// This prints:
///
/// ```text
/// \
/// "
/// ```
///
/// Collecting into a `String`:
/// Using `println!` directly:
///
/// ```
/// let quote: String = '"'.escape_default().collect();
/// println!("{}", '"'.escape_default());
/// ```
///
/// assert_eq!(quote, "\\\"");
///
/// Both are equivalent to:
///
/// ```
/// println!("\\\"");
/// ```
///
/// Using `to_string`:
///
/// ```
/// assert_eq!('"'.escape_default().to_string(), "\\\"");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
@ -726,9 +779,11 @@ impl char {
}
}
/// Returns an iterator that yields the lowercase equivalent of a `char`.
/// Returns an iterator that yields the lowercase equivalent of a `char`
/// as one or more `char`s.
///
/// If no conversion is possible then an iterator with just the input character is returned.
/// If a character does not have a lowercase equivalent, the same character
/// will be returned back by the iterator.
///
/// This performs complex unconditional mappings with no tailoring: it maps
/// one Unicode character to its lowercase equivalent according to the
@ -746,16 +801,37 @@ impl char {
///
/// # Examples
///
/// Basic usage:
/// As an iterator:
///
/// ```
/// assert_eq!('C'.to_lowercase().collect::<String>(), "c");
/// for c in 'İ'.to_lowercase() {
/// print!("{}", c);
/// }
/// println!();
/// ```
///
/// Using `println!` directly:
///
/// ```
/// println!("{}", 'İ'.to_lowercase());
/// ```
///
/// Both are equivalent to:
///
/// ```
/// println!("i\u{307}");
/// ```
///
/// Using `to_string`:
///
/// ```
/// assert_eq!('C'.to_lowercase().to_string(), "c");
///
/// // Sometimes the result is more than one character:
/// assert_eq!('İ'.to_lowercase().collect::<String>(), "i\u{307}");
/// assert_eq!('İ'.to_lowercase().to_string(), "i\u{307}");
///
/// // Japanese scripts do not have case, and so:
/// assert_eq!('山'.to_lowercase().collect::<String>(), "山");
/// assert_eq!('山'.to_lowercase().to_string(), "山");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
@ -763,12 +839,14 @@ impl char {
ToLowercase(CaseMappingIter::new(conversions::to_lower(self)))
}
/// Returns an iterator that yields the uppercase equivalent of a `char`.
/// Returns an iterator that yields the uppercase equivalent of a `char`
/// as one or more `char`s.
///
/// If no conversion is possible then an iterator with just the input character is returned.
/// If a character does not have a uppercase equivalent, the same character
/// will be returned back by the iterator.
///
/// This performs complex unconditional mappings with no tailoring: it maps
/// one Unicode character to its uppercase equivalent according to the
/// one Unicode character to its lowercase equivalent according to the
/// [Unicode database] and the additional complex mappings
/// [`SpecialCasing.txt`]. Conditional mappings (based on context or
/// language) are not considered here.
@ -783,18 +861,41 @@ impl char {
///
/// # Examples
///
/// Basic usage:
/// As an iterator:
///
/// ```
/// assert_eq!('c'.to_uppercase().collect::<String>(), "C");
/// for c in 'ß'.to_uppercase() {
/// print!("{}", c);
/// }
/// println!();
/// ```
///
/// Using `println!` directly:
///
/// ```
/// println!("{}", 'ß'.to_uppercase());
/// ```
///
/// Both are equivalent to:
///
/// ```
/// println!("SS");
/// ```
///
/// Using `to_string`:
///
/// ```
/// assert_eq!('c'.to_uppercase().to_string(), "C");
///
/// // Sometimes the result is more than one character:
/// assert_eq!('ß'.to_uppercase().collect::<String>(), "SS");
/// assert_eq!('ß'.to_uppercase().to_string(), "SS");
///
/// // Japanese does not have case, and so:
/// assert_eq!('山'.to_uppercase().collect::<String>(), "山");
/// assert_eq!('山'.to_uppercase().to_string(), "山");
/// ```
///
/// # Note on locale
///
/// In Turkish, the equivalent of 'i' in Latin has five forms instead of two:
///
/// * 'Dotless': I / ı, sometimes written ï
@ -803,7 +904,7 @@ impl char {
/// Note that the lowercase dotted 'i' is the same as the Latin. Therefore:
///
/// ```
/// let upper_i: String = 'i'.to_uppercase().collect();
/// let upper_i = 'i'.to_uppercase().to_string();
/// ```
///
/// The value of `upper_i` here relies on the language of the text: if we're
@ -811,7 +912,7 @@ impl char {
/// be `"İ"`. `to_uppercase()` does not take this into account, and so:
///
/// ```
/// let upper_i: String = 'i'.to_uppercase().collect();
/// let upper_i = 'i'.to_uppercase().to_string();
///
/// assert_eq!(upper_i, "I");
/// ```