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 pub fn map_into<N : From<F>>(self) -> ChiselError<N, S> {
74 self.map(|x| x.into())
75 }
76}
77
78fn static_unreachable(proof: core::convert::Infallible) -> ! {
83 match proof {}
84}
85
86impl<S> ChiselError<core::convert::Infallible, S> {
87 pub fn from_source(offset: usize, error: ChiselSourceError<S>) -> Self {
89 match error {
90 ChiselSourceError::Underlying(x) => Self::source(offset, x),
91 ChiselSourceError::EndOfInput => Self::end_of_input(offset)
92 }
93 }
94
95 pub fn forward<F>(self) -> ChiselError<F, S> {
104 ChiselError {
105 error: match self.error {
106 ChiselErrorData::EndOfInput => ChiselErrorData::EndOfInput,
107 ChiselErrorData::Source(x) => ChiselErrorData::Source(x),
108 ChiselErrorData::Format(x) => { static_unreachable(x) }
109 },
110 offset: self.offset
111 }
112 }
113}
114
115impl<F : Display, S : Display> Display for ChiselError<F, S> {
116 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
117 f.write_str("couldn't decode: ")?;
118 match &self.error {
119 ChiselErrorData::Format(x) => write!(f, "bad data: {x}"),
120 ChiselErrorData::Source(x) => write!(f, "input error: {x}"),
121 ChiselErrorData::EndOfInput => f.write_str("unexpected end of data")
122 }?;
123 write!(f, " near offset 0x{:08x}", self.offset)
124 }
125}
126
127impl<F : Error + 'static, S : Error + 'static> Error for ChiselError<F, S> {
128 fn cause(&self) -> Option<&(dyn Error + 'static)> {
129 match &self.error {
130 ChiselErrorData::Format(x) => Some(x),
131 ChiselErrorData::Source(x) => Some(x),
132 ChiselErrorData::EndOfInput => None
133 }
134 }
135}