1use std::{string::FromUtf8Error, str::Utf8Error};
2
3use rain_metaboard_subgraph::metaboard_client::MetaboardSubgraphClientError;
4
5use crate::meta::KnownMagic;
6
7#[derive(Debug)]
9pub enum Error {
10 CorruptMeta,
11 InvalidHash,
12 UnknownMeta,
13 UnknownMagic,
14 NoRecordFound,
15 UnsupportedMeta,
16 BiggerThan32Bytes,
17 NulByteInInput,
18 InflateError(String),
19 InvalidInput(String),
20 InvalidUrl(String),
21 Utf8Error(Utf8Error),
22 FromUtf8Error(FromUtf8Error),
23 ReqwestError(reqwest::Error),
24 SerdeCborError(serde_cbor::Error),
25 SerdeJsonError(serde_json::Error),
26 AbiCoderError(alloy::sol_types::Error),
27 ValidationErrors(validator::ValidationErrors),
28 DecodeHexStringError(alloy::primitives::hex::FromHexError),
29 InvalidMetaMagic(KnownMagic, KnownMagic),
30 MetaboardSubgraphClientError(MetaboardSubgraphClientError),
31}
32
33impl std::fmt::Display for Error {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 match self {
36 Error::CorruptMeta => f.write_str("corrupt meta"),
37 Error::UnknownMeta => f.write_str("unknown meta"),
38 Error::UnknownMagic => f.write_str("unknown magic"),
39 Error::UnsupportedMeta => f.write_str("unsupported meta"),
40 Error::InvalidHash => f.write_str("invalid keccak256 hash"),
41 Error::NoRecordFound => f.write_str("found no matching record"),
42 Error::BiggerThan32Bytes => {
43 f.write_str("unexpected input size, must be 32 bytes or less")
44 }
45 Error::NulByteInInput => f.write_str("unexpected nul byte in input"),
46 Error::InvalidInput(v) => write!(f, "invalid input: {}", v),
47 Error::InvalidUrl(v) => write!(f, "invalid URL: {}", v),
48 Error::ReqwestError(v) => write!(f, "{}", v),
49 Error::InflateError(v) => write!(f, "{}", v),
50 Error::Utf8Error(v) => write!(f, "{}", v),
51 Error::AbiCoderError(v) => write!(f, "{}", v),
52 Error::SerdeCborError(v) => write!(f, "{}", v),
53 Error::SerdeJsonError(v) => write!(f, "{}", v),
54 Error::FromUtf8Error(v) => write!(f, "{}", v),
55 Error::DecodeHexStringError(v) => write!(f, "{}", v),
56 Error::ValidationErrors(v) => write!(f, "{}", v),
57 Error::InvalidMetaMagic(expected, actual) => {
58 write!(
59 f,
60 "invalid meta magic: expected {:?}, got {:?}",
61 expected, actual
62 )
63 }
64 Error::MetaboardSubgraphClientError(v) => write!(f, "{}", v),
65 }
66 }
67}
68
69impl std::error::Error for Error {}
70
71impl From<serde_json::Error> for Error {
72 fn from(value: serde_json::Error) -> Self {
73 Error::SerdeJsonError(value)
74 }
75}
76
77impl From<serde_cbor::Error> for Error {
78 fn from(value: serde_cbor::Error) -> Self {
79 Error::SerdeCborError(value)
80 }
81}
82
83impl From<FromUtf8Error> for Error {
84 fn from(value: FromUtf8Error) -> Self {
85 Error::FromUtf8Error(value)
86 }
87}
88
89impl From<Utf8Error> for Error {
90 fn from(value: Utf8Error) -> Self {
91 Error::Utf8Error(value)
92 }
93}
94
95impl From<validator::ValidationErrors> for Error {
96 fn from(value: validator::ValidationErrors) -> Self {
97 Error::ValidationErrors(value)
98 }
99}
100
101impl From<alloy::sol_types::Error> for Error {
102 fn from(value: alloy::sol_types::Error) -> Self {
103 Error::AbiCoderError(value)
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
114 fn test_display_fixed_strings() {
115 assert_eq!(Error::CorruptMeta.to_string(), "corrupt meta");
116 assert_eq!(Error::UnknownMeta.to_string(), "unknown meta");
117 assert_eq!(Error::UnknownMagic.to_string(), "unknown magic");
118 assert_eq!(Error::UnsupportedMeta.to_string(), "unsupported meta");
119 assert_eq!(Error::InvalidHash.to_string(), "invalid keccak256 hash");
120 assert_eq!(Error::NoRecordFound.to_string(), "found no matching record");
121 assert_eq!(
122 Error::BiggerThan32Bytes.to_string(),
123 "unexpected input size, must be 32 bytes or less"
124 );
125 assert_eq!(
126 Error::NulByteInInput.to_string(),
127 "unexpected nul byte in input"
128 );
129 }
130
131 #[test]
133 fn test_display_formatted_wrappers() {
134 assert_eq!(
135 Error::InvalidInput("abc".to_string()).to_string(),
136 "invalid input: abc"
137 );
138 assert_eq!(
139 Error::InvalidUrl("not-a-url".to_string()).to_string(),
140 "invalid URL: not-a-url"
141 );
142 assert_eq!(Error::InflateError("boom".to_string()).to_string(), "boom");
143 }
144
145 #[test]
147 fn test_display_invalid_meta_magic_field_order() {
148 let err = Error::InvalidMetaMagic(KnownMagic::RainMetaDocumentV1, KnownMagic::OpMetaV1);
149 assert_eq!(
150 err.to_string(),
151 "invalid meta magic: expected RainMetaDocumentV1, got OpMetaV1"
152 );
153 }
154
155 #[test]
158 fn test_from_serde_json_routes_to_serde_json_error() {
159 let src = serde_json::from_str::<serde_json::Value>("{oops").unwrap_err();
160 let msg = src.to_string();
161 let err: Error = src.into();
162 match err {
163 Error::SerdeJsonError(e) => assert_eq!(e.to_string(), msg),
164 other => panic!("wrong variant: {:?}", other),
165 }
166 }
167
168 #[test]
169 fn test_from_utf8_error_routes_to_utf8_error() {
170 #[allow(invalid_from_utf8)]
172 let src = std::str::from_utf8(&[0xff]).unwrap_err();
173 let err: Error = src.into();
174 match err {
175 Error::Utf8Error(e) => assert_eq!(e, src),
176 other => panic!("wrong variant: {:?}", other),
177 }
178 }
179
180 #[test]
181 fn test_from_from_utf8_error_routes_to_from_utf8_error() {
182 let src = String::from_utf8(vec![0xff]).unwrap_err();
183 let msg = src.to_string();
184 let err: Error = src.into();
185 match err {
186 Error::FromUtf8Error(e) => assert_eq!(e.to_string(), msg),
187 other => panic!("wrong variant: {:?}", other),
188 }
189 }
190}