1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Error, Debug)]
10pub enum Error {
11 #[error("network error: {0}")]
13 Network(String),
14
15 #[error("storage error: {0}")]
17 Storage(String),
18
19 #[error("payment error: {0}")]
21 Payment(String),
22
23 #[error("protocol error: {0}")]
25 Protocol(String),
26
27 #[error("invalid data: {0}")]
29 InvalidData(String),
30
31 #[error("serialization error: {0}")]
33 Serialization(String),
34
35 #[error("crypto error: {0}")]
37 Crypto(String),
38
39 #[error("I/O error: {0}")]
41 Io(#[from] std::io::Error),
42
43 #[error("configuration error: {0}")]
45 Config(String),
46
47 #[error("timeout: {0}")]
49 Timeout(String),
50
51 #[error("insufficient peers: {0}")]
53 InsufficientPeers(String),
54
55 #[error("signature verification failed: {0}")]
57 SignatureVerification(String),
58
59 #[error("encryption error: {0}")]
61 Encryption(String),
62
63 #[error("already stored on network")]
65 AlreadyStored,
66
67 #[error("bad quote binding from peer {peer_id}: {detail}")]
71 BadQuoteBinding {
72 peer_id: String,
74 detail: String,
76 },
77
78 #[error("insufficient disk space: {0}")]
80 InsufficientDiskSpace(String),
81
82 #[error("cost estimation inconclusive: {0}")]
89 CostEstimationInconclusive(String),
90
91 #[error(
95 "partial upload: {stored_count}/{total_chunks} stored, {failed_count} failed: {reason}"
96 )]
97 PartialUpload {
98 stored: Vec<[u8; 32]>,
100 stored_count: usize,
102 failed: Vec<([u8; 32], String)>,
104 failed_count: usize,
106 total_chunks: usize,
108 reason: String,
110 },
111}
112
113#[cfg(feature = "devnet")]
117impl From<ant_node::Error> for Error {
118 fn from(e: ant_node::Error) -> Self {
119 Self::Network(e.to_string())
120 }
121}
122
123#[cfg(test)]
124#[allow(clippy::unwrap_used, clippy::expect_used)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn test_display_network() {
130 let err = Error::Network("connection refused".to_string());
131 assert_eq!(err.to_string(), "network error: connection refused");
132 }
133
134 #[test]
135 fn test_display_storage() {
136 let err = Error::Storage("disk full".to_string());
137 assert_eq!(err.to_string(), "storage error: disk full");
138 }
139
140 #[test]
141 fn test_display_payment() {
142 let err = Error::Payment("insufficient funds".to_string());
143 assert_eq!(err.to_string(), "payment error: insufficient funds");
144 }
145
146 #[test]
147 fn test_display_protocol() {
148 let err = Error::Protocol("invalid message".to_string());
149 assert_eq!(err.to_string(), "protocol error: invalid message");
150 }
151
152 #[test]
153 fn test_display_invalid_data() {
154 let err = Error::InvalidData("bad hash".to_string());
155 assert_eq!(err.to_string(), "invalid data: bad hash");
156 }
157
158 #[test]
159 fn test_display_serialization() {
160 let err = Error::Serialization("decode failed".to_string());
161 assert_eq!(err.to_string(), "serialization error: decode failed");
162 }
163
164 #[test]
165 fn test_display_crypto() {
166 let err = Error::Crypto("key mismatch".to_string());
167 assert_eq!(err.to_string(), "crypto error: key mismatch");
168 }
169
170 #[test]
171 fn test_display_io() {
172 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file missing");
173 let err = Error::Io(io_err);
174 assert_eq!(err.to_string(), "I/O error: file missing");
175 }
176
177 #[test]
178 fn test_display_config() {
179 let err = Error::Config("bad value".to_string());
180 assert_eq!(err.to_string(), "configuration error: bad value");
181 }
182
183 #[test]
184 fn test_display_timeout() {
185 let err = Error::Timeout("30s elapsed".to_string());
186 assert_eq!(err.to_string(), "timeout: 30s elapsed");
187 }
188
189 #[test]
190 fn test_display_insufficient_peers() {
191 let err = Error::InsufficientPeers("need 5, got 2".to_string());
192 assert_eq!(err.to_string(), "insufficient peers: need 5, got 2");
193 }
194
195 #[test]
196 fn test_display_signature_verification() {
197 let err = Error::SignatureVerification("invalid sig".to_string());
198 assert_eq!(
199 err.to_string(),
200 "signature verification failed: invalid sig"
201 );
202 }
203
204 #[test]
205 fn test_display_encryption() {
206 let err = Error::Encryption("decrypt failed".to_string());
207 assert_eq!(err.to_string(), "encryption error: decrypt failed");
208 }
209
210 #[test]
211 fn test_display_insufficient_disk_space() {
212 let err = Error::InsufficientDiskSpace("need 100 MB but only 10 MB available".to_string());
213 assert_eq!(
214 err.to_string(),
215 "insufficient disk space: need 100 MB but only 10 MB available"
216 );
217 }
218
219 #[test]
220 fn test_display_cost_estimation_inconclusive() {
221 let err = Error::CostEstimationInconclusive(
222 "sampled 5 addresses, all already stored".to_string(),
223 );
224 assert_eq!(
225 err.to_string(),
226 "cost estimation inconclusive: sampled 5 addresses, all already stored"
227 );
228 }
229
230 #[test]
231 fn test_from_io_error() {
232 let io_err = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
233 let err: Error = io_err.into();
234 assert!(matches!(err, Error::Io(_)));
235 }
236}