Skip to main content

object_rainbow/
error.rs

1#[macro_export]
2/// Construct [`Error::Parse`].
3macro_rules! error_parse {
4    ($($t:tt)*) => {
5        $crate::Error::Parse($crate::anyhow!($($t)*))
6    };
7}
8
9#[macro_export]
10/// Construct [`Error::Fetch`].
11macro_rules! error_fetch {
12    ($($t:tt)*) => {
13        $crate::Error::Fetch($crate::anyhow!($($t)*))
14    };
15}
16
17#[macro_export]
18/// Construct [`Error::Operation`].
19macro_rules! error_operation {
20    ($($t:tt)*) => {
21        $crate::Error::Operation($crate::anyhow!($($t)*))
22    };
23}
24
25#[macro_export]
26/// Construct [`Error::Consistency`].
27macro_rules! error_consistency {
28    ($($t:tt)*) => {
29        $crate::Error::Consistency($crate::anyhow!($($t)*))
30    };
31}
32
33/// Errors encountered during fetching an object. Mostly related to parsing.
34#[derive(Debug, thiserror::Error)]
35#[non_exhaustive]
36pub enum Error {
37    /// Arbitrary parsing error.
38    #[error(transparent)]
39    Parse(anyhow::Error),
40    /// Arbitrary fetching error.
41    #[error(transparent)]
42    Fetch(anyhow::Error),
43    /// Arbitrary operation error.
44    #[error(transparent)]
45    Operation(anyhow::Error),
46    /// Arbitrary consistency error.
47    #[error(transparent)]
48    Consistency(anyhow::Error),
49    #[error(transparent)]
50    Io(#[from] std::io::Error),
51    /// Data left after an [`Inline`] got parsed.
52    #[error("extra input left")]
53    ExtraInputLeft,
54    /// EOF.
55    #[error("end of input")]
56    EndOfInput,
57    /// Overran [`PointInput`]'s [`Address`] vector.
58    #[error("address index out of bounds")]
59    AddressOutOfBounds,
60    /// [`Address::hash`] doesn't match what [`Resolve`] returned.
61    #[error("hash resolution mismatch")]
62    ResolutionMismatch,
63    /// [`FullHash::full_hash`] doesn't match [`Singular::hash`].
64    #[error("full hash mismatch")]
65    FullHashMismatch,
66    /// Discriminant out of range for an [`Enum`].
67    #[error("discriminant overflow")]
68    DiscriminantOverflow,
69    /// Unepxected zero for a non-zero value.
70    #[error("zero")]
71    Zero,
72    /// Value out of bounds for a certain type.
73    #[error("out of bounds")]
74    OutOfBounds,
75    /// Current architecture (32-bit) is unable to handle lengths of this size.
76    #[error("length out of bounds")]
77    UnsupportedLength,
78    /// Not UTF-8.
79    #[error(transparent)]
80    Utf8(#[from] std::string::FromUtf8Error),
81    /// [`Resolve::extension`] (or related things) were unable to resolve the extension.
82    #[error("unknown extension")]
83    UnknownExtension,
84    /// Extension type didn't match what we asked for. This might be turned into panic later.
85    #[error("wrong extension type")]
86    ExtensionType,
87    #[error("not implemented")]
88    Unimplemented,
89    #[error("hash not found in the resolve")]
90    HashNotFound,
91    #[error("interrupted")]
92    Interrupted,
93}
94
95impl Error {
96    /// Construct [`Error::Parse`] from another error.
97    pub fn parse(e: impl Into<anyhow::Error>) -> Self {
98        Self::Parse(e.into())
99    }
100
101    /// Construct [`Error::Fetch`] from another error.
102    pub fn fetch(e: impl Into<anyhow::Error>) -> Self {
103        Self::Fetch(e.into())
104    }
105
106    /// Construct [`Error::Operation`] from another error.
107    pub fn operation(e: impl Into<anyhow::Error>) -> Self {
108        Self::Fetch(e.into())
109    }
110
111    /// Construct [`Error::Consistency`] from another error.
112    pub fn consistency(e: impl Into<anyhow::Error>) -> Self {
113        Self::Fetch(e.into())
114    }
115
116    pub fn io(e: impl Into<std::io::Error>) -> Self {
117        e.into().into()
118    }
119
120    fn io_kind(&self) -> std::io::ErrorKind {
121        use std::io::ErrorKind;
122        match self {
123            Error::Parse(_) => ErrorKind::InvalidData,
124            Error::Fetch(_) => ErrorKind::Other,
125            Error::Operation(_) => ErrorKind::Other,
126            Error::Consistency(_) => ErrorKind::InvalidData,
127            Error::Io(e) => e.kind(),
128            Error::ExtraInputLeft => ErrorKind::InvalidData,
129            Error::EndOfInput => ErrorKind::UnexpectedEof,
130            Error::AddressOutOfBounds => ErrorKind::Other,
131            Error::ResolutionMismatch => ErrorKind::InvalidData,
132            Error::FullHashMismatch => ErrorKind::InvalidData,
133            Error::DiscriminantOverflow => ErrorKind::InvalidData,
134            Error::Zero => ErrorKind::InvalidData,
135            Error::OutOfBounds => ErrorKind::InvalidData,
136            Error::UnsupportedLength => ErrorKind::FileTooLarge,
137            Error::Utf8(_) => ErrorKind::InvalidData,
138            Error::UnknownExtension => ErrorKind::Other,
139            Error::ExtensionType => ErrorKind::Other,
140            Error::Unimplemented => ErrorKind::Unsupported,
141            Error::HashNotFound => ErrorKind::NotFound,
142            Error::Interrupted => ErrorKind::Interrupted,
143        }
144    }
145}
146
147impl From<Error> for std::io::Error {
148    fn from(value: Error) -> Self {
149        match value {
150            Error::Io(e) => e,
151            e => Self::new(e.io_kind(), e),
152        }
153    }
154}
155
156pub type Result<T> = std::result::Result<T, Error>;