Skip to content

Commit 8fedc80

Browse files
committed
Clarify UTF-16 decoding errors
1 parent f520900 commit 8fedc80

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`.
@@ -719,7 +728,7 @@ impl String {
719728
let mut ret = String::with_capacity(v.len());
720729
for c in char::decode_utf16(v.iter().cloned()) {
721730
let Ok(c) = c else {
722-
return Err(FromUtf16Error(()));
731+
return Err(FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate });;
723732
};
724733
ret.push(c);
725734
}
@@ -782,13 +791,13 @@ impl String {
782791
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
783792
pub fn from_utf16le(v: &[u8]) -> Result<String, FromUtf16Error> {
784793
let (chunks, []) = v.as_chunks::<2>() else {
785-
return Err(FromUtf16Error(()));
794+
return Err(FromUtf16Error { kind: FromUtf16ErrorKind::OddBytes });
786795
};
787796
match (cfg!(target_endian = "little"), unsafe { v.align_to::<u16>() }) {
788797
(true, ([], v, [])) => Self::from_utf16(v),
789798
_ => char::decode_utf16(chunks.iter().copied().map(u16::from_le_bytes))
790799
.collect::<Result<_, _>>()
791-
.map_err(|_| FromUtf16Error(())),
800+
.map_err(|_| FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate }),
792801
}
793802
}
794803

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

@@ -2329,7 +2338,11 @@ impl fmt::Display for FromUtf8Error {
23292338
#[stable(feature = "rust1", since = "1.0.0")]
23302339
impl fmt::Display for FromUtf16Error {
23312340
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2332-
fmt::Display::fmt("invalid utf-16: lone surrogate found", f)
2341+
match self.kind {
2342+
FromUtf16ErrorKind::LoneSurrogate => "invalid utf-16: lone surrogate found",
2343+
FromUtf16ErrorKind::OddBytes => "invalid utf-16: odd number of bytes",
2344+
}
2345+
.fmt(f)
23332346
}
23342347
}
23352348

0 commit comments

Comments
 (0)