Skip to main content

utf8_bytes/
lib.rs

1//! A deep UTF-8 string library backed by [`bytes`].
2
3extern crate alloc;
4
5mod bytes;
6mod bytes_mut;
7
8use core::fmt;
9
10pub use bytes::Utf8Bytes;
11pub use bytes_mut::Utf8BytesMut;
12
13#[derive(Debug, Clone, PartialEq)]
14pub struct FromUtf8Error<T> {
15    bytes: T,
16    error: core::str::Utf8Error,
17}
18
19impl<T> FromUtf8Error<T> {
20    pub fn inner(&self) -> &T {
21        &self.bytes
22    }
23    pub fn into_inner(self) -> T {
24        self.bytes
25    }
26    pub fn into_utf8_lossy(self) -> Utf8BytesMut
27    where
28        T: Into<Vec<u8>>,
29    {
30        let v = self.into_inner().into();
31        match String::from_utf8_lossy(&v) {
32            std::borrow::Cow::Borrowed(it) => it.into(), // TODO(two allocations)
33            std::borrow::Cow::Owned(it) => it.into(),
34        }
35    }
36    pub fn utf8_error(&self) -> core::str::Utf8Error {
37        self.error
38    }
39}
40
41impl<T> From<FromUtf8Error<T>> for core::str::Utf8Error {
42    fn from(value: FromUtf8Error<T>) -> Self {
43        value.error
44    }
45}
46
47impl<T: fmt::Debug + Send + Sync + 'static> From<FromUtf8Error<T>> for std::io::Error {
48    fn from(value: FromUtf8Error<T>) -> Self {
49        std::io::Error::new(std::io::ErrorKind::InvalidData, value)
50    }
51}
52
53impl<T: fmt::Debug> core::error::Error for FromUtf8Error<T> {
54    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
55        self.error.source()
56    }
57}
58
59impl<T> fmt::Display for FromUtf8Error<T> {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
61        self.error.fmt(f)
62    }
63}