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>>;