utf8_rune/
errors.rs

1use crate::mem::MemoryError;
2
3#[derive(Clone, PartialEq, Eq)]
4pub enum Error<'g> {
5    InvalidIndex(usize, &'g [u8]),
6    UnexpectedContinuationByte(u8, usize, Option<usize>, Option<usize>, &'g [u8]),
7    Utf8Error(usize, &'g [u8], String),
8    MemoryError(MemoryError),
9}
10impl<'g> Error<'g> {
11    pub fn previous_valid_cutoff(&self) -> Option<usize> {
12        match self {
13            Error::InvalidIndex(_, _) => None,
14            Error::UnexpectedContinuationByte(_, _, previous, _, _) => previous.clone(),
15            Error::Utf8Error(_, _, _) => None,
16            Error::MemoryError(_) => None,
17        }
18    }
19
20    pub fn next_valid_cutoff(&self) -> Option<usize> {
21        match self {
22            Error::InvalidIndex(_, _) => None,
23            Error::UnexpectedContinuationByte(_, _, _, next, _) => next.clone(),
24            Error::Utf8Error(_, _, _) => None,
25            Error::MemoryError(_) => None,
26        }
27    }
28}
29impl<'g> std::fmt::Display for Error<'g> {
30    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
31        fn format_slice(slice: &[u8], index: usize) -> String {
32            [
33                format!(
34                    "[{}]",
35                    slice
36                        .into_iter()
37                        .enumerate()
38                        .map(|(i, byte)| if i == index {
39                            format!("\x1b[1;38;5;220m0x{byte:02x}\x1b[0m")
40                        } else {
41                            format!("0x{byte:02x}")
42                        })
43                        .collect::<Vec<String>>()
44                        .join(", ")
45                ),
46                String::from_utf8(slice.to_vec()).unwrap_or_default(),
47            ]
48            .into_iter()
49            .filter(|c| !c.is_empty())
50            .collect::<Vec<String>>()
51            .join(" => ")
52        }
53        write!(
54            f,
55            "{}",
56            match self {
57                Error::InvalidIndex(index, slice) => {
58                    let length = slice.len();
59                    format!(
60                        "invalid index {index}: {index} > {length} in {}",
61                        format_slice(slice, *index)
62                    )
63                },
64                Error::Utf8Error(index, slice, error) => {
65                    format!(
66                        "Utf8Error in index {index} of {}: {error}",
67                        format_slice(slice, *index)
68                    )
69                },
70                Error::MemoryError(error) => {
71                    format!("{:#?}", error)
72                },
73                Error::UnexpectedContinuationByte(
74                    byte,
75                    index,
76                    previous_valid_cutoff,
77                    next_valid_cutoff,
78                    slice,
79                ) => {
80                    [
81                        Some(format!(
82                        "unexpected continuation byte 0x{byte:02x}(0b{byte:08b}) at index {index} of {}",format_slice(slice, *index)
83                        )),
84                        previous_valid_cutoff.map(|previous|format!("previous valid cutoff index: {previous}")),
85                        next_valid_cutoff.map(|next|format!("next valid cutoff index: {next}")),
86                    ].into_iter().filter(|c|c.is_some()).map(|c|c.unwrap().to_string()).collect::<Vec<String>>().join("\n")
87                },
88            }
89        )
90    }
91}
92impl<'g> std::fmt::Debug for Error<'g> {
93    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
94        write!(f, "{self}")
95    }
96}
97impl<'g> std::error::Error for Error<'g> {}
98impl<'g> From<MemoryError> for Error<'g> {
99    fn from(e: MemoryError) -> Error<'g> {
100        Error::MemoryError(e)
101    }
102}
103pub type Result<T> = std::result::Result<T, Error<'static>>;