Skip to main content

object_rainbow/
error.rs

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