Skip to content

Commit 693dc90

Browse files
committed
Clarify UTF-16 decoding errors
1 parent fa1f706 commit 693dc90

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

library/alloc/src/string.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,16 @@ pub struct FromUtf8Error {
410410
/// ```
411411
#[stable(feature = "rust1", since = "1.0.0")]
412412
#[derive(Debug)]
413-
pub struct FromUtf16Error(());
413+
pub struct FromUtf16Error {
414+
kind: FromUtf16ErrorKind,
415+
}
416+
417+
#[cfg_attr(no_global_oom_handling, allow(dead_code))]
418+
#[derive(Clone, PartialEq, Eq, Debug)]
419+
enum FromUtf16ErrorKind {
420+
LoneSurrogate,
421+
OddBytes,
422+
}
414423

415424
impl String {
416425
/// Creates a new empty `String`.
@@ -723,7 +732,7 @@ impl String {
723732
if let Ok(c) = c {
724733
ret.push(c);
725734
} else {
726-
return Err(FromUtf16Error(()));
735+
return Err(FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate });
727736
}
728737
}
729738
Ok(ret)
@@ -785,13 +794,13 @@ impl String {
785794
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
786795
pub fn from_utf16le(v: &[u8]) -> Result<String, FromUtf16Error> {
787796
let (chunks, []) = v.as_chunks::<2>() else {
788-
return Err(FromUtf16Error(()));
797+
return Err(FromUtf16Error { kind: FromUtf16ErrorKind::OddBytes });
789798
};
790799
match (cfg!(target_endian = "little"), unsafe { v.align_to::<u16>() }) {
791800
(true, ([], v, [])) => Self::from_utf16(v),
792801
_ => char::decode_utf16(chunks.iter().copied().map(u16::from_le_bytes))
793802
.collect::<Result<_, _>>()
794-
.map_err(|_| FromUtf16Error(())),
803+
.map_err(|_| FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate }),
795804
}
796805
}
797806

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

@@ -2332,7 +2341,11 @@ impl fmt::Display for FromUtf8Error {
23322341
#[stable(feature = "rust1", since = "1.0.0")]
23332342
impl fmt::Display for FromUtf16Error {
23342343
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2335-
fmt::Display::fmt("invalid utf-16: lone surrogate found", f)
2344+
match self.kind {
2345+
FromUtf16ErrorKind::LoneSurrogate => "invalid utf-16: lone surrogate found",
2346+
FromUtf16ErrorKind::OddBytes => "invalid utf-16: odd number of bytes",
2347+
}
2348+
.fmt(f)
23362349
}
23372350
}
23382351

0 commit comments

Comments
 (0)