hex_conservative/
error.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Error code for the `hex-conservative` crate.
4
5use core::fmt;
6
7use crate::write_err;
8
9/// Formats error.
10///
11/// If `std` feature is OFF appends error source (delimited by `: `). We do this because
12/// `e.source()` is only available in std builds, without this macro the error source is lost for
13/// no-std builds.
14#[macro_export]
15macro_rules! write_err {
16    ($writer:expr, $string:literal $(, $args:expr)*; $source:expr) => {
17        {
18            #[cfg(feature = "std")]
19            {
20                let _ = &$source;   // Prevents clippy warnings.
21                write!($writer, $string $(, $args)*)
22            }
23            #[cfg(not(feature = "std"))]
24            {
25                write!($writer, concat!($string, ": {}") $(, $args)*, $source)
26            }
27        }
28    }
29}
30
31/// Hex decoding error.
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub enum HexToBytesError {
34    /// Non-hexadecimal character.
35    InvalidChar(InvalidCharError),
36    /// Purported hex string had odd length.
37    OddLengthString(OddLengthStringError),
38}
39
40impl fmt::Display for HexToBytesError {
41    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42        use HexToBytesError::*;
43
44        match *self {
45            InvalidChar(ref e) => write_err!(f, "invalid char, failed to create bytes from hex"; e),
46            OddLengthString(ref e) =>
47                write_err!(f, "odd length, failed to create bytes from hex"; e),
48        }
49    }
50}
51
52#[cfg(feature = "std")]
53impl std::error::Error for HexToBytesError {
54    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
55        use HexToBytesError::*;
56
57        match *self {
58            InvalidChar(ref e) => Some(e),
59            OddLengthString(ref e) => Some(e),
60        }
61    }
62}
63
64impl From<InvalidCharError> for HexToBytesError {
65    #[inline]
66    fn from(e: InvalidCharError) -> Self { Self::InvalidChar(e) }
67}
68
69impl From<OddLengthStringError> for HexToBytesError {
70    #[inline]
71    fn from(e: OddLengthStringError) -> Self { Self::OddLengthString(e) }
72}
73
74/// Invalid hex character.
75#[derive(Debug, Clone, PartialEq, Eq)]
76pub struct InvalidCharError {
77    pub(crate) invalid: u8,
78}
79
80impl InvalidCharError {
81    /// Returns the invalid character byte.
82    pub fn invalid_char(&self) -> u8 { self.invalid }
83}
84
85impl fmt::Display for InvalidCharError {
86    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87        write!(f, "invalid hex char {}", self.invalid)
88    }
89}
90
91#[cfg(feature = "std")]
92impl std::error::Error for InvalidCharError {
93    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
94}
95
96/// Purported hex string had odd length.
97#[derive(Debug, Clone, PartialEq, Eq)]
98pub struct OddLengthStringError {
99    pub(crate) len: usize,
100}
101
102impl OddLengthStringError {
103    /// Returns the odd length of the input string.
104    pub fn length(&self) -> usize { self.len }
105}
106
107impl fmt::Display for OddLengthStringError {
108    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109        write!(f, "odd hex string length {}", self.len)
110    }
111}
112
113#[cfg(feature = "std")]
114impl std::error::Error for OddLengthStringError {
115    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
116}
117
118/// Hex decoding error.
119#[derive(Debug, Clone, PartialEq, Eq)]
120pub enum HexToArrayError {
121    /// Non-hexadecimal character.
122    InvalidChar(InvalidCharError),
123    /// Tried to parse fixed-length hash from a string with the wrong length.
124    InvalidLength(InvalidLengthError),
125}
126
127impl fmt::Display for HexToArrayError {
128    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129        use HexToArrayError::*;
130
131        match *self {
132            InvalidChar(ref e) => crate::write_err!(f, "failed to parse hex digit"; e),
133            InvalidLength(ref e) => write_err!(f, "failed to parse hex"; e),
134        }
135    }
136}
137
138#[cfg(feature = "std")]
139impl std::error::Error for HexToArrayError {
140    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
141        use HexToArrayError::*;
142
143        match *self {
144            InvalidChar(ref e) => Some(e),
145            InvalidLength(ref e) => Some(e),
146        }
147    }
148}
149
150impl From<InvalidCharError> for HexToArrayError {
151    #[inline]
152    fn from(e: InvalidCharError) -> Self { Self::InvalidChar(e) }
153}
154
155impl From<InvalidLengthError> for HexToArrayError {
156    #[inline]
157    fn from(e: InvalidLengthError) -> Self { Self::InvalidLength(e) }
158}
159
160/// Tried to parse fixed-length hash from a string with the wrong length.
161#[derive(Debug, Clone, PartialEq, Eq)]
162#[non_exhaustive]
163pub struct InvalidLengthError {
164    /// The expected length.
165    pub expected: usize,
166    /// The invalid length.
167    pub invalid: usize,
168}
169
170impl fmt::Display for InvalidLengthError {
171    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
172        write!(f, "invilad hex string length {} (expected {})", self.invalid, self.expected)
173    }
174}
175
176#[cfg(feature = "std")]
177impl std::error::Error for InvalidLengthError {
178    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
179}