diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index f5ba71c288334..7acd9871fa718 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -410,7 +410,16 @@ pub struct FromUtf8Error { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] -pub struct FromUtf16Error(()); +pub struct FromUtf16Error { + kind: FromUtf16ErrorKind, +} + +#[allow(dead_code)] // Variants are not constructed if no_global_oom_handling is set. +#[derive(Clone, PartialEq, Eq, Debug)] +enum FromUtf16ErrorKind { + LoneSurrogate, + OddBytes, +} impl String { /// Creates a new empty `String`. @@ -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) @@ -785,13 +794,13 @@ impl String { #[unstable(feature = "str_from_utf16_endian", issue = "116258")] pub fn from_utf16le(v: &[u8]) -> Result { 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::() }) { (true, ([], v, [])) => Self::from_utf16(v), _ => char::decode_utf16(chunks.iter().copied().map(u16::from_le_bytes)) .collect::>() - .map_err(|_| FromUtf16Error(())), + .map_err(|_| FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate }), } } @@ -860,13 +869,13 @@ impl String { #[unstable(feature = "str_from_utf16_endian", issue = "116258")] pub fn from_utf16be(v: &[u8]) -> Result { 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::() }) { (true, ([], v, [])) => Self::from_utf16(v), _ => char::decode_utf16(chunks.iter().copied().map(u16::from_be_bytes)) .collect::>() - .map_err(|_| FromUtf16Error(())), + .map_err(|_| FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate }), } } @@ -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) } }