Skip to content

Commit 1900abd

Browse files
committed
Deprecate str::from_utf16_lossy
Use `String::from_utf16_lossy` instead. [breaking-change]
1 parent 6ac4fc7 commit 1900abd

File tree

3 files changed

+111
-106
lines changed

3 files changed

+111
-106
lines changed

src/libcollections/str.rs

+3-105
Original file line numberDiff line numberDiff line change
@@ -384,23 +384,10 @@ pub fn from_utf16(v: &[u16]) -> Option<String> {
384384
String::from_utf16(v)
385385
}
386386

387-
/// Decode a UTF-16 encoded vector `v` into a string, replacing
388-
/// invalid data with the replacement character (U+FFFD).
389-
///
390-
/// # Example
391-
/// ```rust
392-
/// use std::str;
393-
///
394-
/// // 𝄞mus<invalid>ic<invalid>
395-
/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075,
396-
/// 0x0073, 0xDD1E, 0x0069, 0x0063,
397-
/// 0xD834];
398-
///
399-
/// assert_eq!(str::from_utf16_lossy(v),
400-
/// "𝄞mus\uFFFDic\uFFFD".to_string());
401-
/// ```
387+
/// Deprecated. Use `String::from_utf16_lossy`.
388+
#[deprecated = "Replaced by String::from_utf16_lossy"]
402389
pub fn from_utf16_lossy(v: &[u16]) -> String {
403-
utf16_items(v).map(|c| c.to_char_lossy()).collect()
390+
String::from_utf16_lossy(v)
404391
}
405392

406393
// Return the initial codepoint accumulator for the first byte.
@@ -1655,95 +1642,6 @@ mod tests {
16551642
assert!(!"".contains_char('a'));
16561643
}
16571644

1658-
#[test]
1659-
fn test_utf16() {
1660-
let pairs =
1661-
[(String::from_str("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
1662-
vec![0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16,
1663-
0xd800_u16, 0xdf3b_u16, 0xd800_u16, 0xdf46_u16,
1664-
0xd800_u16, 0xdf39_u16, 0xd800_u16, 0xdf3b_u16,
1665-
0xd800_u16, 0xdf30_u16, 0x000a_u16]),
1666-
1667-
(String::from_str("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
1668-
vec![0xd801_u16, 0xdc12_u16, 0xd801_u16,
1669-
0xdc49_u16, 0xd801_u16, 0xdc2e_u16, 0xd801_u16,
1670-
0xdc40_u16, 0xd801_u16, 0xdc32_u16, 0xd801_u16,
1671-
0xdc4b_u16, 0x0020_u16, 0xd801_u16, 0xdc0f_u16,
1672-
0xd801_u16, 0xdc32_u16, 0xd801_u16, 0xdc4d_u16,
1673-
0x000a_u16]),
1674-
1675-
(String::from_str("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
1676-
vec![0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16,
1677-
0xd800_u16, 0xdf0b_u16, 0xd800_u16, 0xdf04_u16,
1678-
0xd800_u16, 0xdf11_u16, 0xd800_u16, 0xdf09_u16,
1679-
0x00b7_u16, 0xd800_u16, 0xdf0c_u16, 0xd800_u16,
1680-
0xdf04_u16, 0xd800_u16, 0xdf15_u16, 0xd800_u16,
1681-
0xdf04_u16, 0xd800_u16, 0xdf0b_u16, 0xd800_u16,
1682-
0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]),
1683-
1684-
(String::from_str("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
1685-
vec![0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16,
1686-
0xd801_u16, 0xdc88_u16, 0xd801_u16, 0xdc91_u16,
1687-
0xd801_u16, 0xdc9b_u16, 0xd801_u16, 0xdc92_u16,
1688-
0x0020_u16, 0xd801_u16, 0xdc95_u16, 0xd801_u16,
1689-
0xdc93_u16, 0x0020_u16, 0xd801_u16, 0xdc88_u16,
1690-
0xd801_u16, 0xdc9a_u16, 0xd801_u16, 0xdc8d_u16,
1691-
0x0020_u16, 0xd801_u16, 0xdc8f_u16, 0xd801_u16,
1692-
0xdc9c_u16, 0xd801_u16, 0xdc92_u16, 0xd801_u16,
1693-
0xdc96_u16, 0xd801_u16, 0xdc86_u16, 0x0020_u16,
1694-
0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16,
1695-
0x000a_u16 ]),
1696-
// Issue #12318, even-numbered non-BMP planes
1697-
(String::from_str("\U00020000"),
1698-
vec![0xD840, 0xDC00])];
1699-
1700-
for p in pairs.iter() {
1701-
let (s, u) = (*p).clone();
1702-
let s_as_utf16 = s.as_slice().utf16_units().collect::<Vec<u16>>();
1703-
let u_as_string = String::from_utf16(u.as_slice()).unwrap();
1704-
1705-
assert!(is_utf16(u.as_slice()));
1706-
assert_eq!(s_as_utf16, u);
1707-
1708-
assert_eq!(u_as_string, s);
1709-
assert_eq!(from_utf16_lossy(u.as_slice()), s);
1710-
1711-
assert_eq!(String::from_utf16(s_as_utf16.as_slice()).unwrap(), s);
1712-
assert_eq!(u_as_string.as_slice().utf16_units().collect::<Vec<u16>>(), u);
1713-
}
1714-
}
1715-
1716-
#[test]
1717-
fn test_utf16_invalid() {
1718-
// completely positive cases tested above.
1719-
// lead + eof
1720-
assert_eq!(String::from_utf16([0xD800]), None);
1721-
// lead + lead
1722-
assert_eq!(String::from_utf16([0xD800, 0xD800]), None);
1723-
1724-
// isolated trail
1725-
assert_eq!(String::from_utf16([0x0061, 0xDC00]), None);
1726-
1727-
// general
1728-
assert_eq!(String::from_utf16([0xD800, 0xd801, 0xdc8b, 0xD800]), None);
1729-
}
1730-
1731-
#[test]
1732-
fn test_utf16_lossy() {
1733-
// completely positive cases tested above.
1734-
// lead + eof
1735-
assert_eq!(from_utf16_lossy([0xD800]), String::from_str("\uFFFD"));
1736-
// lead + lead
1737-
assert_eq!(from_utf16_lossy([0xD800, 0xD800]), String::from_str("\uFFFD\uFFFD"));
1738-
1739-
// isolated trail
1740-
assert_eq!(from_utf16_lossy([0x0061, 0xDC00]), String::from_str("a\uFFFD"));
1741-
1742-
// general
1743-
assert_eq!(from_utf16_lossy([0xD800, 0xd801, 0xdc8b, 0xD800]),
1744-
String::from_str("\uFFFD𐒋\uFFFD"));
1745-
}
1746-
17471645
#[test]
17481646
fn test_truncate_utf16_at_nul() {
17491647
let v = [];

src/libcollections/string.rs

+107
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,23 @@ impl String {
117117
}
118118
Some(s)
119119
}
120+
121+
/// Decode a UTF-16 encoded vector `v` into a string, replacing
122+
/// invalid data with the replacement character (U+FFFD).
123+
///
124+
/// # Example
125+
/// ```rust
126+
/// // 𝄞mus<invalid>ic<invalid>
127+
/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075,
128+
/// 0x0073, 0xDD1E, 0x0069, 0x0063,
129+
/// 0xD834];
130+
///
131+
/// assert_eq!(String::from_utf16_lossy(v),
132+
/// "𝄞mus\uFFFDic\uFFFD".to_string());
133+
/// ```
134+
pub fn from_utf16_lossy(v: &[u16]) -> String {
135+
str::utf16_items(v).map(|c| c.to_char_lossy()).collect()
136+
}
120137

121138
/// Convert a vector of chars to a string
122139
///
@@ -431,6 +448,7 @@ mod tests {
431448
use test::Bencher;
432449

433450
use Mutable;
451+
use str;
434452
use str::{Str, StrSlice};
435453
use super::String;
436454

@@ -439,6 +457,95 @@ mod tests {
439457
let owned: Option<::std::string::String> = from_str("string");
440458
assert_eq!(owned.as_ref().map(|s| s.as_slice()), Some("string"));
441459
}
460+
461+
#[test]
462+
fn test_from_utf16() {
463+
let pairs =
464+
[(String::from_str("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
465+
vec![0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16,
466+
0xd800_u16, 0xdf3b_u16, 0xd800_u16, 0xdf46_u16,
467+
0xd800_u16, 0xdf39_u16, 0xd800_u16, 0xdf3b_u16,
468+
0xd800_u16, 0xdf30_u16, 0x000a_u16]),
469+
470+
(String::from_str("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
471+
vec![0xd801_u16, 0xdc12_u16, 0xd801_u16,
472+
0xdc49_u16, 0xd801_u16, 0xdc2e_u16, 0xd801_u16,
473+
0xdc40_u16, 0xd801_u16, 0xdc32_u16, 0xd801_u16,
474+
0xdc4b_u16, 0x0020_u16, 0xd801_u16, 0xdc0f_u16,
475+
0xd801_u16, 0xdc32_u16, 0xd801_u16, 0xdc4d_u16,
476+
0x000a_u16]),
477+
478+
(String::from_str("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
479+
vec![0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16,
480+
0xd800_u16, 0xdf0b_u16, 0xd800_u16, 0xdf04_u16,
481+
0xd800_u16, 0xdf11_u16, 0xd800_u16, 0xdf09_u16,
482+
0x00b7_u16, 0xd800_u16, 0xdf0c_u16, 0xd800_u16,
483+
0xdf04_u16, 0xd800_u16, 0xdf15_u16, 0xd800_u16,
484+
0xdf04_u16, 0xd800_u16, 0xdf0b_u16, 0xd800_u16,
485+
0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]),
486+
487+
(String::from_str("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
488+
vec![0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16,
489+
0xd801_u16, 0xdc88_u16, 0xd801_u16, 0xdc91_u16,
490+
0xd801_u16, 0xdc9b_u16, 0xd801_u16, 0xdc92_u16,
491+
0x0020_u16, 0xd801_u16, 0xdc95_u16, 0xd801_u16,
492+
0xdc93_u16, 0x0020_u16, 0xd801_u16, 0xdc88_u16,
493+
0xd801_u16, 0xdc9a_u16, 0xd801_u16, 0xdc8d_u16,
494+
0x0020_u16, 0xd801_u16, 0xdc8f_u16, 0xd801_u16,
495+
0xdc9c_u16, 0xd801_u16, 0xdc92_u16, 0xd801_u16,
496+
0xdc96_u16, 0xd801_u16, 0xdc86_u16, 0x0020_u16,
497+
0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16,
498+
0x000a_u16 ]),
499+
// Issue #12318, even-numbered non-BMP planes
500+
(String::from_str("\U00020000"),
501+
vec![0xD840, 0xDC00])];
502+
503+
for p in pairs.iter() {
504+
let (s, u) = (*p).clone();
505+
let s_as_utf16 = s.as_slice().utf16_units().collect::<Vec<u16>>();
506+
let u_as_string = String::from_utf16(u.as_slice()).unwrap();
507+
508+
assert!(str::is_utf16(u.as_slice()));
509+
assert_eq!(s_as_utf16, u);
510+
511+
assert_eq!(u_as_string, s);
512+
assert_eq!(String::from_utf16_lossy(u.as_slice()), s);
513+
514+
assert_eq!(String::from_utf16(s_as_utf16.as_slice()).unwrap(), s);
515+
assert_eq!(u_as_string.as_slice().utf16_units().collect::<Vec<u16>>(), u);
516+
}
517+
}
518+
519+
#[test]
520+
fn test_utf16_invalid() {
521+
// completely positive cases tested above.
522+
// lead + eof
523+
assert_eq!(String::from_utf16([0xD800]), None);
524+
// lead + lead
525+
assert_eq!(String::from_utf16([0xD800, 0xD800]), None);
526+
527+
// isolated trail
528+
assert_eq!(String::from_utf16([0x0061, 0xDC00]), None);
529+
530+
// general
531+
assert_eq!(String::from_utf16([0xD800, 0xd801, 0xdc8b, 0xD800]), None);
532+
}
533+
534+
#[test]
535+
fn test_from_utf16_lossy() {
536+
// completely positive cases tested above.
537+
// lead + eof
538+
assert_eq!(String::from_utf16_lossy([0xD800]), String::from_str("\uFFFD"));
539+
// lead + lead
540+
assert_eq!(String::from_utf16_lossy([0xD800, 0xD800]), String::from_str("\uFFFD\uFFFD"));
541+
542+
// isolated trail
543+
assert_eq!(String::from_utf16_lossy([0x0061, 0xDC00]), String::from_str("a\uFFFD"));
544+
545+
// general
546+
assert_eq!(String::from_utf16_lossy([0xD800, 0xd801, 0xdc8b, 0xD800]),
547+
String::from_str("\uFFFD𐒋\uFFFD"));
548+
}
442549

443550
#[bench]
444551
fn bench_with_capacity(b: &mut Bencher) {

src/libstd/os.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ pub fn env_as_bytes() -> Vec<(Vec<u8>,Vec<u8>)> {
266266
let p = &*ch.offset(i);
267267
let len = ptr::position(p, |c| *c == 0);
268268
raw::buf_as_slice(p, len, |s| {
269-
result.push(str::from_utf16_lossy(s).into_bytes());
269+
result.push(String::from_utf16_lossy(s).into_bytes());
270270
});
271271
i += len as int + 1;
272272
}

0 commit comments

Comments
 (0)