bec64090a7
This is the name that was decided in rust-lang/rfcs#1152, and it's better if we say “boxed str” for `Box<str>`. The old name `String::into_boxed_slice` is deprecated.
504 lines
14 KiB
Rust
504 lines
14 KiB
Rust
// 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.
|
||
|
||
use std::borrow::{IntoCow, Cow};
|
||
use std::iter::repeat;
|
||
|
||
use test::Bencher;
|
||
|
||
#[test]
|
||
fn test_from_str() {
|
||
let owned: Option<::std::string::String> = "string".parse().ok();
|
||
assert_eq!(owned.as_ref().map(|s| &**s), Some("string"));
|
||
}
|
||
|
||
#[test]
|
||
fn test_unsized_to_string() {
|
||
let s: &str = "abc";
|
||
let _: String = (*s).to_string();
|
||
}
|
||
|
||
#[test]
|
||
fn test_from_utf8() {
|
||
let xs = b"hello".to_vec();
|
||
assert_eq!(String::from_utf8(xs).unwrap(),
|
||
String::from("hello"));
|
||
|
||
let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
|
||
assert_eq!(String::from_utf8(xs).unwrap(),
|
||
String::from("ศไทย中华Việt Nam"));
|
||
|
||
let xs = b"hello\xFF".to_vec();
|
||
let err = String::from_utf8(xs).err().unwrap();
|
||
assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
|
||
}
|
||
|
||
#[test]
|
||
fn test_from_utf8_lossy() {
|
||
let xs = b"hello";
|
||
let ys: Cow<str> = "hello".into_cow();
|
||
assert_eq!(String::from_utf8_lossy(xs), ys);
|
||
|
||
let xs = "ศไทย中华Việt Nam".as_bytes();
|
||
let ys: Cow<str> = "ศไทย中华Việt Nam".into_cow();
|
||
assert_eq!(String::from_utf8_lossy(xs), ys);
|
||
|
||
let xs = b"Hello\xC2 There\xFF Goodbye";
|
||
assert_eq!(String::from_utf8_lossy(xs),
|
||
String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow());
|
||
|
||
let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
|
||
assert_eq!(String::from_utf8_lossy(xs),
|
||
String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow());
|
||
|
||
let xs = b"\xF5foo\xF5\x80bar";
|
||
assert_eq!(String::from_utf8_lossy(xs),
|
||
String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow());
|
||
|
||
let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
|
||
assert_eq!(String::from_utf8_lossy(xs),
|
||
String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow());
|
||
|
||
let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
|
||
assert_eq!(String::from_utf8_lossy(xs),
|
||
String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow());
|
||
|
||
let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
|
||
assert_eq!(String::from_utf8_lossy(xs), String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}\
|
||
foo\u{10000}bar").into_cow());
|
||
|
||
// surrogates
|
||
let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
|
||
assert_eq!(String::from_utf8_lossy(xs), String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\
|
||
\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow());
|
||
}
|
||
|
||
#[test]
|
||
fn test_from_utf16() {
|
||
let pairs =
|
||
[(String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
|
||
vec![0xd800, 0xdf45, 0xd800, 0xdf3f,
|
||
0xd800, 0xdf3b, 0xd800, 0xdf46,
|
||
0xd800, 0xdf39, 0xd800, 0xdf3b,
|
||
0xd800, 0xdf30, 0x000a]),
|
||
|
||
(String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
|
||
vec![0xd801, 0xdc12, 0xd801,
|
||
0xdc49, 0xd801, 0xdc2e, 0xd801,
|
||
0xdc40, 0xd801, 0xdc32, 0xd801,
|
||
0xdc4b, 0x0020, 0xd801, 0xdc0f,
|
||
0xd801, 0xdc32, 0xd801, 0xdc4d,
|
||
0x000a]),
|
||
|
||
(String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
|
||
vec![0xd800, 0xdf00, 0xd800, 0xdf16,
|
||
0xd800, 0xdf0b, 0xd800, 0xdf04,
|
||
0xd800, 0xdf11, 0xd800, 0xdf09,
|
||
0x00b7, 0xd800, 0xdf0c, 0xd800,
|
||
0xdf04, 0xd800, 0xdf15, 0xd800,
|
||
0xdf04, 0xd800, 0xdf0b, 0xd800,
|
||
0xdf09, 0xd800, 0xdf11, 0x000a ]),
|
||
|
||
(String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
|
||
vec![0xd801, 0xdc8b, 0xd801, 0xdc98,
|
||
0xd801, 0xdc88, 0xd801, 0xdc91,
|
||
0xd801, 0xdc9b, 0xd801, 0xdc92,
|
||
0x0020, 0xd801, 0xdc95, 0xd801,
|
||
0xdc93, 0x0020, 0xd801, 0xdc88,
|
||
0xd801, 0xdc9a, 0xd801, 0xdc8d,
|
||
0x0020, 0xd801, 0xdc8f, 0xd801,
|
||
0xdc9c, 0xd801, 0xdc92, 0xd801,
|
||
0xdc96, 0xd801, 0xdc86, 0x0020,
|
||
0xd801, 0xdc95, 0xd801, 0xdc86,
|
||
0x000a ]),
|
||
// Issue #12318, even-numbered non-BMP planes
|
||
(String::from("\u{20000}"),
|
||
vec![0xD840, 0xDC00])];
|
||
|
||
for p in &pairs {
|
||
let (s, u) = (*p).clone();
|
||
let s_as_utf16 = s.utf16_units().collect::<Vec<u16>>();
|
||
let u_as_string = String::from_utf16(&u).unwrap();
|
||
|
||
assert!(::rustc_unicode::str::is_utf16(&u));
|
||
assert_eq!(s_as_utf16, u);
|
||
|
||
assert_eq!(u_as_string, s);
|
||
assert_eq!(String::from_utf16_lossy(&u), s);
|
||
|
||
assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s);
|
||
assert_eq!(u_as_string.utf16_units().collect::<Vec<u16>>(), u);
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn test_utf16_invalid() {
|
||
// completely positive cases tested above.
|
||
// lead + eof
|
||
assert!(String::from_utf16(&[0xD800]).is_err());
|
||
// lead + lead
|
||
assert!(String::from_utf16(&[0xD800, 0xD800]).is_err());
|
||
|
||
// isolated trail
|
||
assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err());
|
||
|
||
// general
|
||
assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err());
|
||
}
|
||
|
||
#[test]
|
||
fn test_from_utf16_lossy() {
|
||
// completely positive cases tested above.
|
||
// lead + eof
|
||
assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}"));
|
||
// lead + lead
|
||
assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]),
|
||
String::from("\u{FFFD}\u{FFFD}"));
|
||
|
||
// isolated trail
|
||
assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}"));
|
||
|
||
// general
|
||
assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
|
||
String::from("\u{FFFD}𐒋\u{FFFD}"));
|
||
}
|
||
|
||
#[test]
|
||
fn test_push_bytes() {
|
||
let mut s = String::from("ABC");
|
||
unsafe {
|
||
let mv = s.as_mut_vec();
|
||
mv.push_all(&[b'D']);
|
||
}
|
||
assert_eq!(s, "ABCD");
|
||
}
|
||
|
||
#[test]
|
||
fn test_push_str() {
|
||
let mut s = String::new();
|
||
s.push_str("");
|
||
assert_eq!(&s[0..], "");
|
||
s.push_str("abc");
|
||
assert_eq!(&s[0..], "abc");
|
||
s.push_str("ประเทศไทย中华Việt Nam");
|
||
assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
|
||
}
|
||
|
||
#[test]
|
||
fn test_push() {
|
||
let mut data = String::from("ประเทศไทย中");
|
||
data.push('华');
|
||
data.push('b'); // 1 byte
|
||
data.push('¢'); // 2 byte
|
||
data.push('€'); // 3 byte
|
||
data.push('𤭢'); // 4 byte
|
||
assert_eq!(data, "ประเทศไทย中华b¢€𤭢");
|
||
}
|
||
|
||
#[test]
|
||
fn test_pop() {
|
||
let mut data = String::from("ประเทศไทย中华b¢€𤭢");
|
||
assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes
|
||
assert_eq!(data.pop().unwrap(), '€'); // 3 bytes
|
||
assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes
|
||
assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes
|
||
assert_eq!(data.pop().unwrap(), '华');
|
||
assert_eq!(data, "ประเทศไทย中");
|
||
}
|
||
|
||
#[test]
|
||
fn test_str_truncate() {
|
||
let mut s = String::from("12345");
|
||
s.truncate(5);
|
||
assert_eq!(s, "12345");
|
||
s.truncate(3);
|
||
assert_eq!(s, "123");
|
||
s.truncate(0);
|
||
assert_eq!(s, "");
|
||
|
||
let mut s = String::from("12345");
|
||
let p = s.as_ptr();
|
||
s.truncate(3);
|
||
s.push_str("6");
|
||
let p_ = s.as_ptr();
|
||
assert_eq!(p_, p);
|
||
}
|
||
|
||
#[test]
|
||
#[should_panic]
|
||
fn test_str_truncate_invalid_len() {
|
||
let mut s = String::from("12345");
|
||
s.truncate(6);
|
||
}
|
||
|
||
#[test]
|
||
#[should_panic]
|
||
fn test_str_truncate_split_codepoint() {
|
||
let mut s = String::from("\u{FC}"); // ü
|
||
s.truncate(1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_str_clear() {
|
||
let mut s = String::from("12345");
|
||
s.clear();
|
||
assert_eq!(s.len(), 0);
|
||
assert_eq!(s, "");
|
||
}
|
||
|
||
#[test]
|
||
fn test_str_add() {
|
||
let a = String::from("12345");
|
||
let b = a + "2";
|
||
let b = b + "2";
|
||
assert_eq!(b.len(), 7);
|
||
assert_eq!(b, "1234522");
|
||
}
|
||
|
||
#[test]
|
||
fn remove() {
|
||
let mut s = "ศไทย中华Việt Nam; foobar".to_string();;
|
||
assert_eq!(s.remove(0), 'ศ');
|
||
assert_eq!(s.len(), 33);
|
||
assert_eq!(s, "ไทย中华Việt Nam; foobar");
|
||
assert_eq!(s.remove(17), 'ệ');
|
||
assert_eq!(s, "ไทย中华Vit Nam; foobar");
|
||
}
|
||
|
||
#[test] #[should_panic]
|
||
fn remove_bad() {
|
||
"ศ".to_string().remove(1);
|
||
}
|
||
|
||
#[test]
|
||
fn insert() {
|
||
let mut s = "foobar".to_string();
|
||
s.insert(0, 'ệ');
|
||
assert_eq!(s, "ệfoobar");
|
||
s.insert(6, 'ย');
|
||
assert_eq!(s, "ệfooยbar");
|
||
}
|
||
|
||
#[test] #[should_panic] fn insert_bad1() { "".to_string().insert(1, 't'); }
|
||
#[test] #[should_panic] fn insert_bad2() { "ệ".to_string().insert(1, 't'); }
|
||
|
||
#[test]
|
||
fn test_slicing() {
|
||
let s = "foobar".to_string();
|
||
assert_eq!("foobar", &s[..]);
|
||
assert_eq!("foo", &s[..3]);
|
||
assert_eq!("bar", &s[3..]);
|
||
assert_eq!("oob", &s[1..4]);
|
||
}
|
||
|
||
#[test]
|
||
fn test_simple_types() {
|
||
assert_eq!(1.to_string(), "1");
|
||
assert_eq!((-1).to_string(), "-1");
|
||
assert_eq!(200.to_string(), "200");
|
||
assert_eq!(2.to_string(), "2");
|
||
assert_eq!(true.to_string(), "true");
|
||
assert_eq!(false.to_string(), "false");
|
||
assert_eq!(("hi".to_string()).to_string(), "hi");
|
||
}
|
||
|
||
#[test]
|
||
fn test_vectors() {
|
||
let x: Vec<i32> = vec![];
|
||
assert_eq!(format!("{:?}", x), "[]");
|
||
assert_eq!(format!("{:?}", vec![1]), "[1]");
|
||
assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]");
|
||
assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) ==
|
||
"[[], [1], [1, 1]]");
|
||
}
|
||
|
||
#[test]
|
||
fn test_from_iterator() {
|
||
let s = "ศไทย中华Việt Nam".to_string();
|
||
let t = "ศไทย中华";
|
||
let u = "Việt Nam";
|
||
|
||
let a: String = s.chars().collect();
|
||
assert_eq!(s, a);
|
||
|
||
let mut b = t.to_string();
|
||
b.extend(u.chars());
|
||
assert_eq!(s, b);
|
||
|
||
let c: String = vec![t, u].into_iter().collect();
|
||
assert_eq!(s, c);
|
||
|
||
let mut d = t.to_string();
|
||
d.extend(vec![u]);
|
||
assert_eq!(s, d);
|
||
}
|
||
|
||
#[test]
|
||
fn test_drain() {
|
||
let mut s = String::from("αβγ");
|
||
assert_eq!(s.drain(2..4).collect::<String>(), "β");
|
||
assert_eq!(s, "αγ");
|
||
|
||
let mut t = String::from("abcd");
|
||
t.drain(..0);
|
||
assert_eq!(t, "abcd");
|
||
t.drain(..1);
|
||
assert_eq!(t, "bcd");
|
||
t.drain(3..);
|
||
assert_eq!(t, "bcd");
|
||
t.drain(..);
|
||
assert_eq!(t, "");
|
||
}
|
||
|
||
#[test]
|
||
fn test_extend_ref() {
|
||
let mut a = "foo".to_string();
|
||
a.extend(&['b', 'a', 'r']);
|
||
|
||
assert_eq!(&a, "foobar");
|
||
}
|
||
|
||
#[test]
|
||
fn test_into_boxed_str() {
|
||
let xs = String::from("hello my name is bob");
|
||
let ys = xs.into_boxed_str();
|
||
assert_eq!(&*ys, "hello my name is bob");
|
||
}
|
||
|
||
#[bench]
|
||
fn bench_with_capacity(b: &mut Bencher) {
|
||
b.iter(|| {
|
||
String::with_capacity(100)
|
||
});
|
||
}
|
||
|
||
#[bench]
|
||
fn bench_push_str(b: &mut Bencher) {
|
||
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
|
||
b.iter(|| {
|
||
let mut r = String::new();
|
||
r.push_str(s);
|
||
});
|
||
}
|
||
|
||
const REPETITIONS: u64 = 10_000;
|
||
|
||
#[bench]
|
||
fn bench_push_str_one_byte(b: &mut Bencher) {
|
||
b.bytes = REPETITIONS;
|
||
b.iter(|| {
|
||
let mut r = String::new();
|
||
for _ in 0..REPETITIONS {
|
||
r.push_str("a")
|
||
}
|
||
});
|
||
}
|
||
|
||
#[bench]
|
||
fn bench_push_char_one_byte(b: &mut Bencher) {
|
||
b.bytes = REPETITIONS;
|
||
b.iter(|| {
|
||
let mut r = String::new();
|
||
for _ in 0..REPETITIONS {
|
||
r.push('a')
|
||
}
|
||
});
|
||
}
|
||
|
||
#[bench]
|
||
fn bench_push_char_two_bytes(b: &mut Bencher) {
|
||
b.bytes = REPETITIONS * 2;
|
||
b.iter(|| {
|
||
let mut r = String::new();
|
||
for _ in 0..REPETITIONS {
|
||
r.push('â')
|
||
}
|
||
});
|
||
}
|
||
|
||
#[bench]
|
||
fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
|
||
let s = b"Hello there, the quick brown fox jumped over the lazy dog! \
|
||
Lorem ipsum dolor sit amet, consectetur. ";
|
||
|
||
assert_eq!(100, s.len());
|
||
b.iter(|| {
|
||
let _ = String::from_utf8_lossy(s);
|
||
});
|
||
}
|
||
|
||
#[bench]
|
||
fn from_utf8_lossy_100_multibyte(b: &mut Bencher) {
|
||
let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes();
|
||
assert_eq!(100, s.len());
|
||
b.iter(|| {
|
||
let _ = String::from_utf8_lossy(s);
|
||
});
|
||
}
|
||
|
||
#[bench]
|
||
fn from_utf8_lossy_invalid(b: &mut Bencher) {
|
||
let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
|
||
b.iter(|| {
|
||
let _ = String::from_utf8_lossy(s);
|
||
});
|
||
}
|
||
|
||
#[bench]
|
||
fn from_utf8_lossy_100_invalid(b: &mut Bencher) {
|
||
let s = repeat(0xf5).take(100).collect::<Vec<_>>();
|
||
b.iter(|| {
|
||
let _ = String::from_utf8_lossy(&s);
|
||
});
|
||
}
|
||
|
||
#[bench]
|
||
fn bench_exact_size_shrink_to_fit(b: &mut Bencher) {
|
||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||
Lorem ipsum dolor sit amet, consectetur. ";
|
||
// ensure our operation produces an exact-size string before we benchmark it
|
||
let mut r = String::with_capacity(s.len());
|
||
r.push_str(s);
|
||
assert_eq!(r.len(), r.capacity());
|
||
b.iter(|| {
|
||
let mut r = String::with_capacity(s.len());
|
||
r.push_str(s);
|
||
r.shrink_to_fit();
|
||
r
|
||
});
|
||
}
|
||
|
||
#[bench]
|
||
fn bench_from_str(b: &mut Bencher) {
|
||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||
Lorem ipsum dolor sit amet, consectetur. ";
|
||
b.iter(|| {
|
||
String::from(s)
|
||
})
|
||
}
|
||
|
||
#[bench]
|
||
fn bench_from(b: &mut Bencher) {
|
||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||
Lorem ipsum dolor sit amet, consectetur. ";
|
||
b.iter(|| {
|
||
String::from(s)
|
||
})
|
||
}
|
||
|
||
#[bench]
|
||
fn bench_to_string(b: &mut Bencher) {
|
||
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
|
||
Lorem ipsum dolor sit amet, consectetur. ";
|
||
b.iter(|| {
|
||
s.to_string()
|
||
})
|
||
}
|