diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 64abdca32d211..4c8f7242efddc 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, +} + +#[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`. @@ -719,7 +728,7 @@ impl String { let mut ret = String::with_capacity(v.len()); for c in char::decode_utf16(v.iter().cloned()) { let Ok(c) = c else { - return Err(FromUtf16Error(())); + return Err(FromUtf16Error { kind: FromUtf16ErrorKind::LoneSurrogate }); }; ret.push(c); } @@ -782,13 +791,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 }), } } @@ -857,13 +866,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 }), } } @@ -2329,7 +2338,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) } }