1use core::error::Error;
2use core::fmt::Display;
3use crate::source::ChiselSourceError;
4
5#[derive(Debug)]
7pub enum ChiselErrorData<F, S> {
8 Format(F),
10 Source(S),
12 EndOfInput
14}
15
16#[derive(Debug)]
29pub struct ChiselError<F, S> {
30 pub offset: usize,
36 pub error: ChiselErrorData<F, S>
38}
39
40impl<F, S> ChiselError<F, S> {
41 pub fn new(offset: usize, error: ChiselErrorData<F, S>) -> Self { Self { offset, error } }
43 pub fn end_of_input(offset: usize) -> Self { Self { offset, error: ChiselErrorData::EndOfInput } }
45 pub fn source(offset: usize, error: S) -> Self { Self { offset, error: ChiselErrorData::Source(error) } }
47 pub fn format(offset: usize, error: F) -> Self { Self { offset, error: ChiselErrorData::Format(error) } }
49
50 pub fn map<M : FnOnce(F) -> N, N>(self, mapper: M) -> ChiselError<N, S> {
58 ChiselError {
59 offset: self.offset,
60 error: match self.error {
61 ChiselErrorData::EndOfInput => ChiselErrorData::EndOfInput,
62 ChiselErrorData::Format(x) => ChiselErrorData::Format(mapper(x)),
63 ChiselErrorData::Source(x) => ChiselErrorData::Source(x)
64 }
65 }
66 }
67}
68
69fn static_unreachable(proof: core::convert::Infallible) -> ! {
74 match proof {}
75}
76
77impl<S> ChiselError<core::convert::Infallible, S> {
78 pub fn from_source(offset: usize, error: ChiselSourceError<S>) -> Self {
80 match error {
81 ChiselSourceError::Underlying(x) => Self::source(offset, x),
82 ChiselSourceError::EndOfInput => Self::end_of_input(offset)
83 }
84 }
85
86 pub fn forward<F>(self) -> ChiselError<F, S> {
95 ChiselError {
96 error: match self.error {
97 ChiselErrorData::EndOfInput => ChiselErrorData::EndOfInput,
98 ChiselErrorData::Source(x) => ChiselErrorData::Source(x),
99 ChiselErrorData::Format(x) => { static_unreachable(x) }
100 },
101 offset: self.offset
102 }
103 }
104}
105
106impl<F : Display, S : Display> Display for ChiselError<F, S> {
107 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
108 f.write_str("couldn't decode: ")?;
109 match &self.error {
110 ChiselErrorData::Format(x) => write!(f, "bad data: {x}"),
111 ChiselErrorData::Source(x) => write!(f, "input error: {x}"),
112 ChiselErrorData::EndOfInput => f.write_str("unexpected end of data")
113 }?;
114 write!(f, " near offset 0x{:08x}", self.offset)
115 }
116}
117
118impl<F : Error + 'static, S : Error + 'static> Error for ChiselError<F, S> {
119 fn cause(&self) -> Option<&(dyn Error + 'static)> {
120 match &self.error {
121 ChiselErrorData::Format(x) => Some(x),
122 ChiselErrorData::Source(x) => Some(x),
123 ChiselErrorData::EndOfInput => None
124 }
125 }
126}