Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions library/alloc/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,16 @@ pub struct FromUtf8Error {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct FromUtf16Error(());
pub struct FromUtf16Error {
kind: FromUtf16ErrorKind,
}

#[cfg_attr(no_global_oom_handling, allow(dead_code))]
#[derive(Clone, PartialEq, Eq, Debug)]
enum FromUtf16ErrorKind {
LoneSurrogate,
OddBytes,
}

impl String {
/// Creates a new empty `String`.
Expand Down Expand Up @@ -723,7 +732,7 @@ impl String {
if let Ok(c) = c {
ret.push(c);
} else {
return Err(FromUtf16Error(()));
return Err(FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate });
}
}
Ok(ret)
Expand Down Expand Up @@ -785,13 +794,13 @@ impl String {
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
pub fn from_utf16le(v: &[u8]) -> Result<String, FromUtf16Error> {
let (chunks, []) = v.as_chunks::<2>() else {
return Err(FromUtf16Error(()));
return Err(FromUtf16Error { kind: FromUtf16ErrorKind::OddBytes });
};
match (cfg!(target_endian = "little"), unsafe { v.align_to::<u16>() }) {
(true, ([], v, [])) => Self::from_utf16(v),
_ => char::decode_utf16(chunks.iter().copied().map(u16::from_le_bytes))
.collect::<Result<_, _>>()
.map_err(|_| FromUtf16Error(())),
.map_err(|_| FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate }),
}
}

Expand Down Expand Up @@ -860,13 +869,13 @@ impl String {
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
pub fn from_utf16be(v: &[u8]) -> Result<String, FromUtf16Error> {
let (chunks, []) = v.as_chunks::<2>() else {
return Err(FromUtf16Error(()));
return Err(FromUtf16Error { kind: FromUtf16ErrorKind::OddBytes });
};
match (cfg!(target_endian = "big"), unsafe { v.align_to::<u16>() }) {
(true, ([], v, [])) => Self::from_utf16(v),
_ => char::decode_utf16(chunks.iter().copied().map(u16::from_be_bytes))
.collect::<Result<_, _>>()
.map_err(|_| FromUtf16Error(())),
.map_err(|_| FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate }),
}
}

Expand Down Expand Up @@ -2332,7 +2341,11 @@ impl fmt::Display for FromUtf8Error {
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for FromUtf16Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt("invalid utf-16: lone surrogate found", f)
match self.kind {
FromUtf16ErrorKind::LoneSurrogate => "invalid utf-16: lone surrogate found",
FromUtf16ErrorKind::OddBytes => "invalid utf-16: odd number of bytes",
}
.fmt(f)
}
}

Expand Down
Loading