2014-06-28 15:57:36 -05:00
|
|
|
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
2016-04-07 12:42:53 -05:00
|
|
|
|
use std::char;
|
|
|
|
|
|
2014-06-28 15:57:36 -05:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_is_lowercase() {
|
|
|
|
|
assert!('a'.is_lowercase());
|
|
|
|
|
assert!('ö'.is_lowercase());
|
|
|
|
|
assert!('ß'.is_lowercase());
|
|
|
|
|
assert!(!'Ü'.is_lowercase());
|
|
|
|
|
assert!(!'P'.is_lowercase());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_is_uppercase() {
|
|
|
|
|
assert!(!'h'.is_uppercase());
|
|
|
|
|
assert!(!'ä'.is_uppercase());
|
|
|
|
|
assert!(!'ß'.is_uppercase());
|
|
|
|
|
assert!('Ö'.is_uppercase());
|
|
|
|
|
assert!('T'.is_uppercase());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_is_whitespace() {
|
|
|
|
|
assert!(' '.is_whitespace());
|
2015-01-02 01:53:35 -06:00
|
|
|
|
assert!('\u{2007}'.is_whitespace());
|
2014-06-28 15:57:36 -05:00
|
|
|
|
assert!('\t'.is_whitespace());
|
|
|
|
|
assert!('\n'.is_whitespace());
|
|
|
|
|
assert!(!'a'.is_whitespace());
|
|
|
|
|
assert!(!'_'.is_whitespace());
|
2015-01-02 01:53:35 -06:00
|
|
|
|
assert!(!'\u{0}'.is_whitespace());
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_to_digit() {
|
2015-02-03 07:50:52 -06:00
|
|
|
|
assert_eq!('0'.to_digit(10), Some(0));
|
|
|
|
|
assert_eq!('1'.to_digit(2), Some(1));
|
|
|
|
|
assert_eq!('2'.to_digit(3), Some(2));
|
|
|
|
|
assert_eq!('9'.to_digit(10), Some(9));
|
|
|
|
|
assert_eq!('a'.to_digit(16), Some(10));
|
|
|
|
|
assert_eq!('A'.to_digit(16), Some(10));
|
|
|
|
|
assert_eq!('b'.to_digit(16), Some(11));
|
|
|
|
|
assert_eq!('B'.to_digit(16), Some(11));
|
|
|
|
|
assert_eq!('z'.to_digit(36), Some(35));
|
|
|
|
|
assert_eq!('Z'.to_digit(36), Some(35));
|
|
|
|
|
assert_eq!(' '.to_digit(10), None);
|
|
|
|
|
assert_eq!('$'.to_digit(36), None);
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_to_lowercase() {
|
2015-08-20 07:38:46 -05:00
|
|
|
|
fn lower(c: char) -> Vec<char> {
|
|
|
|
|
c.to_lowercase().collect()
|
2015-03-05 20:23:57 -06:00
|
|
|
|
}
|
2015-08-20 07:38:46 -05:00
|
|
|
|
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}']);
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_to_uppercase() {
|
2015-06-09 04:37:08 -05:00
|
|
|
|
fn upper(c: char) -> Vec<char> {
|
|
|
|
|
c.to_uppercase().collect()
|
2015-03-05 20:23:57 -06:00
|
|
|
|
}
|
2015-06-09 04:37:08 -05:00
|
|
|
|
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('💩'), ['💩']);
|
2014-06-28 15:57:36 -05:00
|
|
|
|
|
2015-06-09 04:37:08 -05:00
|
|
|
|
assert_eq!(upper('σ'), ['Σ']);
|
|
|
|
|
assert_eq!(upper('τ'), ['Τ']);
|
|
|
|
|
assert_eq!(upper('ι'), ['Ι']);
|
|
|
|
|
assert_eq!(upper('γ'), ['Γ']);
|
|
|
|
|
assert_eq!(upper('μ'), ['Μ']);
|
|
|
|
|
assert_eq!(upper('α'), ['Α']);
|
|
|
|
|
assert_eq!(upper('ς'), ['Σ']);
|
2015-06-09 04:38:11 -05:00
|
|
|
|
assert_eq!(upper('Dž'), ['DŽ']);
|
|
|
|
|
assert_eq!(upper('fi'), ['F', 'I']);
|
|
|
|
|
assert_eq!(upper('ᾀ'), ['Ἀ', 'Ι']);
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 15:57:36 -05:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_is_control() {
|
2015-01-02 01:53:35 -06:00
|
|
|
|
assert!('\u{0}'.is_control());
|
|
|
|
|
assert!('\u{3}'.is_control());
|
|
|
|
|
assert!('\u{6}'.is_control());
|
|
|
|
|
assert!('\u{9}'.is_control());
|
|
|
|
|
assert!('\u{7f}'.is_control());
|
|
|
|
|
assert!('\u{92}'.is_control());
|
|
|
|
|
assert!(!'\u{20}'.is_control());
|
|
|
|
|
assert!(!'\u{55}'.is_control());
|
|
|
|
|
assert!(!'\u{68}'.is_control());
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_is_digit() {
|
2014-10-08 19:15:27 -05:00
|
|
|
|
assert!('2'.is_numeric());
|
|
|
|
|
assert!('7'.is_numeric());
|
|
|
|
|
assert!(!'c'.is_numeric());
|
|
|
|
|
assert!(!'i'.is_numeric());
|
|
|
|
|
assert!(!'z'.is_numeric());
|
|
|
|
|
assert!(!'Q'.is_numeric());
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2016-07-27 05:10:31 -05:00
|
|
|
|
fn test_escape_debug() {
|
2014-06-28 15:57:36 -05:00
|
|
|
|
fn string(c: char) -> String {
|
2016-07-27 05:10:31 -05:00
|
|
|
|
c.escape_debug().collect()
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
let s = string('\n');
|
2014-11-27 12:12:30 -06:00
|
|
|
|
assert_eq!(s, "\\n");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('\r');
|
2014-11-27 12:12:30 -06:00
|
|
|
|
assert_eq!(s, "\\r");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('\'');
|
2014-11-27 12:12:30 -06:00
|
|
|
|
assert_eq!(s, "\\'");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('"');
|
2014-11-27 12:12:30 -06:00
|
|
|
|
assert_eq!(s, "\\\"");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string(' ');
|
2014-11-27 12:12:30 -06:00
|
|
|
|
assert_eq!(s, " ");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('a');
|
2014-11-27 12:12:30 -06:00
|
|
|
|
assert_eq!(s, "a");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('~');
|
2014-11-27 12:12:30 -06:00
|
|
|
|
assert_eq!(s, "~");
|
Escape fewer Unicode codepoints in `Debug` impl of `str`
Use the same procedure as Python to determine whether a character is
printable, described in [PEP 3138]. In particular, this means that the
following character classes are escaped:
- Cc (Other, Control)
- Cf (Other, Format)
- Cs (Other, Surrogate), even though they can't appear in Rust strings
- Co (Other, Private Use)
- Cn (Other, Not Assigned)
- Zl (Separator, Line)
- Zp (Separator, Paragraph)
- Zs (Separator, Space), except for the ASCII space `' '` (`0x20`)
This allows for user-friendly inspection of strings that are not
English (e.g. compare `"\u{e9}\u{e8}\u{ea}"` to `"éèê"`).
Fixes #34318.
[PEP 3138]: https://www.python.org/dev/peps/pep-3138/
2016-06-26 08:11:48 -05:00
|
|
|
|
let s = string('é');
|
|
|
|
|
assert_eq!(s, "é");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('\x00');
|
2014-12-15 10:49:01 -06:00
|
|
|
|
assert_eq!(s, "\\u{0}");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('\x1f');
|
2014-12-15 10:49:01 -06:00
|
|
|
|
assert_eq!(s, "\\u{1f}");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('\x7f');
|
2014-12-15 10:49:01 -06:00
|
|
|
|
assert_eq!(s, "\\u{7f}");
|
Escape fewer Unicode codepoints in `Debug` impl of `str`
Use the same procedure as Python to determine whether a character is
printable, described in [PEP 3138]. In particular, this means that the
following character classes are escaped:
- Cc (Other, Control)
- Cf (Other, Format)
- Cs (Other, Surrogate), even though they can't appear in Rust strings
- Co (Other, Private Use)
- Cn (Other, Not Assigned)
- Zl (Separator, Line)
- Zp (Separator, Paragraph)
- Zs (Separator, Space), except for the ASCII space `' '` (`0x20`)
This allows for user-friendly inspection of strings that are not
English (e.g. compare `"\u{e9}\u{e8}\u{ea}"` to `"éèê"`).
Fixes #34318.
[PEP 3138]: https://www.python.org/dev/peps/pep-3138/
2016-06-26 08:11:48 -05:00
|
|
|
|
let s = string('\u{80}');
|
|
|
|
|
assert_eq!(s, "\\u{80}");
|
2014-12-15 10:49:01 -06:00
|
|
|
|
let s = string('\u{ff}');
|
Escape fewer Unicode codepoints in `Debug` impl of `str`
Use the same procedure as Python to determine whether a character is
printable, described in [PEP 3138]. In particular, this means that the
following character classes are escaped:
- Cc (Other, Control)
- Cf (Other, Format)
- Cs (Other, Surrogate), even though they can't appear in Rust strings
- Co (Other, Private Use)
- Cn (Other, Not Assigned)
- Zl (Separator, Line)
- Zp (Separator, Paragraph)
- Zs (Separator, Space), except for the ASCII space `' '` (`0x20`)
This allows for user-friendly inspection of strings that are not
English (e.g. compare `"\u{e9}\u{e8}\u{ea}"` to `"éèê"`).
Fixes #34318.
[PEP 3138]: https://www.python.org/dev/peps/pep-3138/
2016-06-26 08:11:48 -05:00
|
|
|
|
assert_eq!(s, "\u{ff}");
|
2014-12-15 10:49:01 -06:00
|
|
|
|
let s = string('\u{11b}');
|
Escape fewer Unicode codepoints in `Debug` impl of `str`
Use the same procedure as Python to determine whether a character is
printable, described in [PEP 3138]. In particular, this means that the
following character classes are escaped:
- Cc (Other, Control)
- Cf (Other, Format)
- Cs (Other, Surrogate), even though they can't appear in Rust strings
- Co (Other, Private Use)
- Cn (Other, Not Assigned)
- Zl (Separator, Line)
- Zp (Separator, Paragraph)
- Zs (Separator, Space), except for the ASCII space `' '` (`0x20`)
This allows for user-friendly inspection of strings that are not
English (e.g. compare `"\u{e9}\u{e8}\u{ea}"` to `"éèê"`).
Fixes #34318.
[PEP 3138]: https://www.python.org/dev/peps/pep-3138/
2016-06-26 08:11:48 -05:00
|
|
|
|
assert_eq!(s, "\u{11b}");
|
2014-12-15 10:49:01 -06:00
|
|
|
|
let s = string('\u{1d4b6}');
|
Escape fewer Unicode codepoints in `Debug` impl of `str`
Use the same procedure as Python to determine whether a character is
printable, described in [PEP 3138]. In particular, this means that the
following character classes are escaped:
- Cc (Other, Control)
- Cf (Other, Format)
- Cs (Other, Surrogate), even though they can't appear in Rust strings
- Co (Other, Private Use)
- Cn (Other, Not Assigned)
- Zl (Separator, Line)
- Zp (Separator, Paragraph)
- Zs (Separator, Space), except for the ASCII space `' '` (`0x20`)
This allows for user-friendly inspection of strings that are not
English (e.g. compare `"\u{e9}\u{e8}\u{ea}"` to `"éèê"`).
Fixes #34318.
[PEP 3138]: https://www.python.org/dev/peps/pep-3138/
2016-06-26 08:11:48 -05:00
|
|
|
|
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}");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
2016-07-25 18:39:54 -05:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_escape_default() {
|
|
|
|
|
fn string(c: char) -> String {
|
|
|
|
|
c.escape_default().collect()
|
|
|
|
|
}
|
|
|
|
|
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}");
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 15:57:36 -05:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_escape_unicode() {
|
2014-12-15 10:49:01 -06:00
|
|
|
|
fn string(c: char) -> String { c.escape_unicode().collect() }
|
|
|
|
|
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('\x00');
|
2014-12-15 10:49:01 -06:00
|
|
|
|
assert_eq!(s, "\\u{0}");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('\n');
|
2014-12-15 10:49:01 -06:00
|
|
|
|
assert_eq!(s, "\\u{a}");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string(' ');
|
2014-12-15 10:49:01 -06:00
|
|
|
|
assert_eq!(s, "\\u{20}");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
let s = string('a');
|
2014-12-15 10:49:01 -06:00
|
|
|
|
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}");
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_encode_utf8() {
|
|
|
|
|
fn check(input: char, expect: &[u8]) {
|
2016-03-11 13:01:46 -06:00
|
|
|
|
assert_eq!(input.encode_utf8().as_slice(), expect);
|
|
|
|
|
for (a, b) in input.encode_utf8().zip(expect) {
|
|
|
|
|
assert_eq!(a, *b);
|
|
|
|
|
}
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
2014-11-17 02:39:01 -06:00
|
|
|
|
check('x', &[0x78]);
|
2015-01-02 01:53:35 -06:00
|
|
|
|
check('\u{e9}', &[0xc3, 0xa9]);
|
|
|
|
|
check('\u{a66e}', &[0xea, 0x99, 0xae]);
|
|
|
|
|
check('\u{1f4a9}', &[0xf0, 0x9f, 0x92, 0xa9]);
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_encode_utf16() {
|
|
|
|
|
fn check(input: char, expect: &[u16]) {
|
2016-03-11 13:01:46 -06:00
|
|
|
|
assert_eq!(input.encode_utf16().as_slice(), expect);
|
|
|
|
|
for (a, b) in input.encode_utf16().zip(expect) {
|
|
|
|
|
assert_eq!(a, *b);
|
|
|
|
|
}
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
|
|
|
|
|
2014-11-17 02:39:01 -06:00
|
|
|
|
check('x', &[0x0078]);
|
2015-01-02 01:53:35 -06:00
|
|
|
|
check('\u{e9}', &[0x00e9]);
|
|
|
|
|
check('\u{a66e}', &[0xa66e]);
|
|
|
|
|
check('\u{1f4a9}', &[0xd83d, 0xdca9]);
|
2014-06-28 15:57:36 -05:00
|
|
|
|
}
|
Add libunicode; move unicode functions from core
- created new crate, libunicode, below libstd
- split Char trait into Char (libcore) and UnicodeChar (libunicode)
- Unicode-aware functions now live in libunicode
- is_alphabetic, is_XID_start, is_XID_continue, is_lowercase,
is_uppercase, is_whitespace, is_alphanumeric, is_control,
is_digit, to_uppercase, to_lowercase
- added width method in UnicodeChar trait
- determines printed width of character in columns, or None if it is
a non-NULL control character
- takes a boolean argument indicating whether the present context is
CJK or not (characters with 'A'mbiguous widths are double-wide in
CJK contexts, single-wide otherwise)
- split StrSlice into StrSlice (libcore) and UnicodeStrSlice
(libunicode)
- functionality formerly in StrSlice that relied upon Unicode
functionality from Char is now in UnicodeStrSlice
- words, is_whitespace, is_alphanumeric, trim, trim_left, trim_right
- also moved Words type alias into libunicode because words method is
in UnicodeStrSlice
- unified Unicode tables from libcollections, libcore, and libregex into
libunicode
- updated unicode.py in src/etc to generate aforementioned tables
- generated new tables based on latest Unicode data
- added UnicodeChar and UnicodeStrSlice traits to prelude
- libunicode is now the collection point for the std::char module,
combining the libunicode functionality with the Char functionality
from libcore
- thus, moved doc comment for char from core::char to unicode::char
- libcollections remains the collection point for std::str
The Unicode-aware functions that previously lived in the Char and
StrSlice traits are no longer available to programs that only use
libcore. To regain use of these methods, include the libunicode crate
and use the UnicodeChar and/or UnicodeStrSlice traits:
extern crate unicode;
use unicode::UnicodeChar;
use unicode::UnicodeStrSlice;
use unicode::Words; // if you want to use the words() method
NOTE: this does *not* impact programs that use libstd, since UnicodeChar
and UnicodeStrSlice have been added to the prelude.
closes #15224
[breaking-change]
2014-06-30 16:04:10 -05:00
|
|
|
|
|
2014-10-08 19:40:31 -05:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_len_utf16() {
|
|
|
|
|
assert!('x'.len_utf16() == 1);
|
2015-01-02 01:53:35 -06:00
|
|
|
|
assert!('\u{e9}'.len_utf16() == 1);
|
|
|
|
|
assert!('\u{a66e}'.len_utf16() == 1);
|
|
|
|
|
assert!('\u{1f4a9}'.len_utf16() == 2);
|
2014-10-08 19:40:31 -05:00
|
|
|
|
}
|
2015-08-13 11:39:46 -05:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_decode_utf16() {
|
|
|
|
|
fn check(s: &[u16], expected: &[Result<char, u16>]) {
|
2016-04-07 12:42:53 -05:00
|
|
|
|
let v = char::decode_utf16(s.iter().cloned())
|
|
|
|
|
.map(|r| r.map_err(|e| e.unpaired_surrogate()))
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
assert_eq!(v, expected);
|
2015-08-13 11:39:46 -05:00
|
|
|
|
}
|
|
|
|
|
check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]);
|
|
|
|
|
check(&[0xD800, 0], &[Err(0xD800), Ok('\0')]);
|
|
|
|
|
}
|
2016-01-12 07:35:04 -06:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn ed_iterator_specializations() {
|
|
|
|
|
// Check counting
|
|
|
|
|
assert_eq!('\n'.escape_default().count(), 2);
|
|
|
|
|
assert_eq!('c'.escape_default().count(), 1);
|
|
|
|
|
assert_eq!(' '.escape_default().count(), 1);
|
|
|
|
|
assert_eq!('\\'.escape_default().count(), 2);
|
|
|
|
|
assert_eq!('\''.escape_default().count(), 2);
|
|
|
|
|
|
|
|
|
|
// Check nth
|
|
|
|
|
|
|
|
|
|
// Check that OoB is handled correctly
|
|
|
|
|
assert_eq!('\n'.escape_default().nth(2), None);
|
|
|
|
|
assert_eq!('c'.escape_default().nth(1), None);
|
|
|
|
|
assert_eq!(' '.escape_default().nth(1), None);
|
|
|
|
|
assert_eq!('\\'.escape_default().nth(2), None);
|
|
|
|
|
assert_eq!('\''.escape_default().nth(2), None);
|
|
|
|
|
|
|
|
|
|
// Check the first char
|
|
|
|
|
assert_eq!('\n'.escape_default().nth(0), Some('\\'));
|
|
|
|
|
assert_eq!('c'.escape_default().nth(0), Some('c'));
|
|
|
|
|
assert_eq!(' '.escape_default().nth(0), Some(' '));
|
|
|
|
|
assert_eq!('\\'.escape_default().nth(0), Some('\\'));
|
|
|
|
|
assert_eq!('\''.escape_default().nth(0), Some('\\'));
|
|
|
|
|
|
|
|
|
|
// Check the second char
|
|
|
|
|
assert_eq!('\n'.escape_default().nth(1), Some('n'));
|
|
|
|
|
assert_eq!('\\'.escape_default().nth(1), Some('\\'));
|
|
|
|
|
assert_eq!('\''.escape_default().nth(1), Some('\''));
|
|
|
|
|
|
|
|
|
|
// Check the last char
|
|
|
|
|
assert_eq!('\n'.escape_default().last(), Some('n'));
|
|
|
|
|
assert_eq!('c'.escape_default().last(), Some('c'));
|
|
|
|
|
assert_eq!(' '.escape_default().last(), Some(' '));
|
|
|
|
|
assert_eq!('\\'.escape_default().last(), Some('\\'));
|
|
|
|
|
assert_eq!('\''.escape_default().last(), Some('\''));
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-04 05:08:11 -05:00
|
|
|
|
#[test]
|
|
|
|
|
fn eu_iterator_specializations() {
|
|
|
|
|
fn check(c: char) {
|
|
|
|
|
let len = c.escape_unicode().count();
|
|
|
|
|
|
|
|
|
|
// Check OoB
|
|
|
|
|
assert_eq!(c.escape_unicode().nth(len), None);
|
|
|
|
|
|
|
|
|
|
// For all possible in-bound offsets
|
|
|
|
|
let mut iter = c.escape_unicode();
|
|
|
|
|
for offset in 0..len {
|
|
|
|
|
// Check last
|
|
|
|
|
assert_eq!(iter.clone().last(), Some('}'));
|
2016-01-12 07:35:04 -06:00
|
|
|
|
|
2016-05-26 03:54:58 -05:00
|
|
|
|
// Check len
|
|
|
|
|
assert_eq!(iter.len(), len - offset);
|
|
|
|
|
|
|
|
|
|
// Check size_hint (= len in ExactSizeIterator)
|
|
|
|
|
assert_eq!(iter.size_hint(), (iter.len(), Some(iter.len())));
|
|
|
|
|
|
2016-05-04 05:08:11 -05:00
|
|
|
|
// Check counting
|
|
|
|
|
assert_eq!(iter.clone().count(), len - offset);
|
|
|
|
|
|
|
|
|
|
// Check nth
|
|
|
|
|
assert_eq!(c.escape_unicode().nth(offset), iter.next());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check post-last
|
|
|
|
|
assert_eq!(iter.clone().last(), None);
|
|
|
|
|
assert_eq!(iter.clone().count(), 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check('\u{0}');
|
|
|
|
|
check('\u{1}');
|
|
|
|
|
check('\u{12}');
|
|
|
|
|
check('\u{123}');
|
|
|
|
|
check('\u{1234}');
|
|
|
|
|
check('\u{12340}');
|
|
|
|
|
check('\u{10FFFF}');
|
|
|
|
|
}
|
2016-05-27 11:16:27 -05:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_decode_utf8() {
|
2016-08-23 10:26:34 -05:00
|
|
|
|
macro_rules! assert_decode_utf8 {
|
|
|
|
|
($input_bytes: expr, $expected_str: expr) => {
|
|
|
|
|
let input_bytes: &[u8] = &$input_bytes;
|
|
|
|
|
let s = char::decode_utf8(input_bytes.iter().cloned())
|
|
|
|
|
.map(|r_b| r_b.unwrap_or('\u{FFFD}'))
|
|
|
|
|
.collect::<String>();
|
|
|
|
|
assert_eq!(s, $expected_str,
|
|
|
|
|
"input bytes: {:?}, expected str: {:?}, result: {:?}",
|
|
|
|
|
input_bytes, $expected_str, s);
|
2016-08-23 15:09:59 -05:00
|
|
|
|
assert_eq!(String::from_utf8_lossy(&$input_bytes), $expected_str);
|
2016-08-23 10:26:34 -05:00
|
|
|
|
}
|
2016-05-27 11:16:27 -05:00
|
|
|
|
}
|
2016-08-23 10:26:34 -05:00
|
|
|
|
|
|
|
|
|
assert_decode_utf8!([], "");
|
|
|
|
|
assert_decode_utf8!([0x41], "A");
|
2016-08-23 15:09:59 -05:00
|
|
|
|
assert_decode_utf8!([0xC1, 0x81], "<EFBFBD><EFBFBD>");
|
2016-08-23 10:26:34 -05:00
|
|
|
|
assert_decode_utf8!([0xE2, 0x99, 0xA5], "♥");
|
|
|
|
|
assert_decode_utf8!([0xE2, 0x99, 0xA5, 0x41], "♥A");
|
|
|
|
|
assert_decode_utf8!([0xE2, 0x99], "<EFBFBD>");
|
|
|
|
|
assert_decode_utf8!([0xE2, 0x99, 0x41], "<EFBFBD>A");
|
|
|
|
|
assert_decode_utf8!([0xC0], "<EFBFBD>");
|
|
|
|
|
assert_decode_utf8!([0xC0, 0x41], "<EFBFBD>A");
|
|
|
|
|
assert_decode_utf8!([0x80], "<EFBFBD>");
|
|
|
|
|
assert_decode_utf8!([0x80, 0x41], "<EFBFBD>A");
|
|
|
|
|
assert_decode_utf8!([0xFE], "<EFBFBD>");
|
|
|
|
|
assert_decode_utf8!([0xFE, 0x41], "<EFBFBD>A");
|
|
|
|
|
assert_decode_utf8!([0xFF], "<EFBFBD>");
|
|
|
|
|
assert_decode_utf8!([0xFF, 0x41], "<EFBFBD>A");
|
2016-08-23 15:09:59 -05:00
|
|
|
|
assert_decode_utf8!([0xC0, 0x80], "<EFBFBD><EFBFBD>");
|
|
|
|
|
|
|
|
|
|
// Surrogates
|
|
|
|
|
assert_decode_utf8!([0xED, 0x9F, 0xBF], "\u{D7FF}");
|
|
|
|
|
assert_decode_utf8!([0xED, 0xA0, 0x80], "<EFBFBD><EFBFBD><EFBFBD>");
|
|
|
|
|
assert_decode_utf8!([0xED, 0xBF, 0x80], "<EFBFBD><EFBFBD><EFBFBD>");
|
|
|
|
|
assert_decode_utf8!([0xEE, 0x80, 0x80], "\u{E000}");
|
|
|
|
|
|
|
|
|
|
// char::MAX
|
|
|
|
|
assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0xBF], "\u{10FFFF}");
|
|
|
|
|
assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0x41], "<EFBFBD>A");
|
|
|
|
|
assert_decode_utf8!([0xF4, 0x90, 0x80, 0x80], "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
|
|
|
|
|
|
|
|
|
// 5 and 6 bytes sequence
|
|
|
|
|
// Part of the original design of UTF-8,
|
|
|
|
|
// but invalid now that UTF-8 is artificially restricted to match the range of UTF-16.
|
|
|
|
|
assert_decode_utf8!([0xF8, 0x80, 0x80, 0x80, 0x80], "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
|
|
|
|
assert_decode_utf8!([0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
2016-05-27 11:16:27 -05:00
|
|
|
|
}
|