Skip to content

Commit 2279962

Browse files
committed
Clarify UTF-16 decoding errors
1 parent 29e035e commit 2279962

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+
#[allow(dead_code)] // Variants are not constructed if no_global_oom_handling is set.
418+
#[derive(Clone, PartialEq, Eq, Debug)]
419+
enum FromUtf16ErrorKind {
420+
LoneSurrogate,
421+
OddBytes,
422+
}
414423

415424
impl String {
416425
/// Creates a new empty `String`.
@@ -719,7 +728,7 @@ impl String {
719728
if let Ok(c) = c {
720729
ret.push(c);
721730
} else {
722-
return Err(FromUtf16Error(()));
731+
return Err(FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate });
723732
}
724733
}
725734
Ok(ret)
@@ -781,13 +790,13 @@ impl String {
781790
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
782791
pub fn from_utf16le(v: &[u8]) -> Result<String, FromUtf16Error> {
783792
let (chunks, []) = v.as_chunks::<2>() else {
784-
return Err(FromUtf16Error(()));
793+
return Err(FromUtf16Error { kind: FromUtf16ErrorKind::OddBytes });
785794
};
786795
match (cfg!(target_endian = "little"), unsafe { v.align_to::<u16>() }) {
787796
(true, ([], v, [])) => Self::from_utf16(v),
788797
_ => char::decode_utf16(chunks.iter().copied().map(u16::from_le_bytes))
789798
.collect::<Result<_, _>>()
790-
.map_err(|_| FromUtf16Error(())),
799+
.map_err(|_| FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate }),
791800
}
792801
}
793802

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

@@ -2319,7 +2328,11 @@ impl fmt::Display for FromUtf8Error {
23192328
#[stable(feature = "rust1", since = "1.0.0")]
23202329
impl fmt::Display for FromUtf16Error {
23212330
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2322-
fmt::Display::fmt("invalid utf-16: lone surrogate found", f)
2331+
match self.kind {
2332+
FromUtf16ErrorKind::LoneSurrogate => "invalid utf-16: lone surrogate found",
2333+
FromUtf16ErrorKind::OddBytes => "invalid utf-16: odd number of bytes",
2334+
}
2335+
.fmt(f)
23232336
}
23242337
}
23252338

0 commit comments

Comments
 (0)