use core::fmt::Display;
use core::fmt::Formatter;
use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut};
use crate::implementation::validate_utf8_compat;
#[derive(Copy, Eq, PartialEq, Clone, Debug)]
pub struct Utf8Error {
pub(crate) valid_up_to: usize,
pub(crate) error_len: Option<u8>,
}
impl Utf8Error {
#[inline]
#[must_use]
#[allow(clippy::missing_const_for_fn)] pub fn valid_up_to(&self) -> usize {
self.valid_up_to
}
#[inline]
#[must_use]
pub fn error_len(&self) -> Option<usize> {
self.error_len.map(|len| len as usize)
}
}
impl Display for Utf8Error {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
if let Some(error_len) = self.error_len {
write!(
f,
"invalid utf-8 sequence of {} bytes from index {}",
error_len, self.valid_up_to
)
} else {
write!(
f,
"incomplete utf-8 byte sequence from index {}",
self.valid_up_to
)
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Utf8Error {}
#[inline]
pub fn from_utf8(input: &[u8]) -> Result<&str, Utf8Error> {
unsafe {
validate_utf8_compat(input)?;
Ok(from_utf8_unchecked(input))
}
}
#[inline]
pub fn from_utf8_mut(input: &mut [u8]) -> Result<&mut str, Utf8Error> {
unsafe {
validate_utf8_compat(input)?;
Ok(from_utf8_unchecked_mut(input))
}
}
#[cfg(feature = "public_imp")]
pub mod imp {
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64")))]
pub mod x86 {
pub mod avx2 {
pub use crate::implementation::x86::avx2::validate_utf8_compat as validate_utf8;
}
pub mod sse42 {
pub use crate::implementation::x86::sse42::validate_utf8_compat as validate_utf8;
}
}
#[cfg(all(feature = "aarch64_neon", target_arch = "aarch64"))]
pub mod aarch64 {
pub mod neon {
pub use crate::implementation::aarch64::neon::validate_utf8_compat as validate_utf8;
}
}
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
pub mod wasm32 {
pub mod simd128 {
pub use crate::implementation::wasm32::simd128::validate_utf8_compat as validate_utf8;
}
}
}