java_string/
error.rs

1use std::error::Error;
2use std::fmt;
3use std::fmt::{Display, Formatter};
4
5#[derive(Copy, Eq, PartialEq, Clone, Debug)]
6pub struct Utf8Error {
7    pub(crate) valid_up_to: usize,
8    pub(crate) error_len: Option<u8>,
9}
10
11impl Utf8Error {
12    #[must_use]
13    #[inline]
14    pub const fn valid_up_to(&self) -> usize {
15        self.valid_up_to
16    }
17
18    #[must_use]
19    #[inline]
20    pub const fn error_len(&self) -> Option<usize> {
21        // Manual implementation of Option::map since it's not const
22        match self.error_len {
23            Some(len) => Some(len as usize),
24            None => None,
25        }
26    }
27
28    #[must_use]
29    #[inline]
30    pub(crate) const fn from_std(value: std::str::Utf8Error) -> Self {
31        Self {
32            valid_up_to: value.valid_up_to(),
33            // Manual implementation of Option::map since it's not const
34            error_len: match value.error_len() {
35                Some(error_len) => Some(error_len as u8),
36                None => None,
37            },
38        }
39    }
40}
41
42impl Display for Utf8Error {
43    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
44        if let Some(error_len) = self.error_len {
45            write!(
46                f,
47                "invalid utf-8 sequence of {} bytes from index {}",
48                error_len, self.valid_up_to
49            )
50        } else {
51            write!(
52                f,
53                "incomplete utf-8 byte sequence from index {}",
54                self.valid_up_to
55            )
56        }
57    }
58}
59
60impl From<std::str::Utf8Error> for Utf8Error {
61    #[inline]
62    fn from(value: std::str::Utf8Error) -> Self {
63        Self::from_std(value)
64    }
65}
66
67impl Error for Utf8Error {}
68
69#[derive(Clone, Debug, PartialEq, Eq)]
70pub struct FromUtf8Error {
71    pub(crate) bytes: Vec<u8>,
72    pub(crate) error: Utf8Error,
73}
74
75impl FromUtf8Error {
76    pub fn as_bytes(&self) -> &[u8] {
77        &self.bytes[..]
78    }
79
80    #[must_use]
81    pub fn into_bytes(self) -> Vec<u8> {
82        self.bytes
83    }
84
85    pub fn utf8_error(&self) -> Utf8Error {
86        self.error
87    }
88}
89
90impl Display for FromUtf8Error {
91    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
92        Display::fmt(&self.error, f)
93    }
94}
95
96impl Error for FromUtf8Error {}
97
98#[derive(Copy, Eq, PartialEq, Clone, Debug)]
99pub enum ParseError<E> {
100    InvalidUtf8(Utf8Error),
101    Err(E),
102}
103
104impl<E> Display for ParseError<E>
105where
106    E: Display,
107{
108    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
109        match self {
110            ParseError::InvalidUtf8(err) => Display::fmt(err, f),
111            ParseError::Err(err) => Display::fmt(err, f),
112        }
113    }
114}
115
116impl<E> Error for ParseError<E>
117where
118    E: Error + 'static,
119{
120    fn source(&self) -> Option<&(dyn Error + 'static)> {
121        match self {
122            ParseError::InvalidUtf8(err) => Some(err),
123            ParseError::Err(err) => Some(err),
124        }
125    }
126}