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("insufficient disk space: {0}")]
69 InsufficientDiskSpace(String),
70
71 #[error("cost estimation inconclusive: {0}")]
78 CostEstimationInconclusive(String),
79
80 #[error(
84 "partial upload: {stored_count}/{total_chunks} stored, {failed_count} failed: {reason}"
85 )]
86 PartialUpload {
87 stored: Vec<[u8; 32]>,
89 stored_count: usize,
91 failed: Vec<([u8; 32], String)>,
93 failed_count: usize,
95 total_chunks: usize,
97 reason: String,
99 },
100}
101
102#[cfg(feature = "devnet")]
106impl From<ant_node::Error> for Error {
107 fn from(e: ant_node::Error) -> Self {
108 Self::Network(e.to_string())
109 }
110}
111
112#[cfg(test)]
113#[allow(clippy::unwrap_used, clippy::expect_used)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_display_network() {
119 let err = Error::Network("connection refused".to_string());
120 assert_eq!(err.to_string(), "network error: connection refused");
121 }
122
123 #[test]
124 fn test_display_storage() {
125 let err = Error::Storage("disk full".to_string());
126 assert_eq!(err.to_string(), "storage error: disk full");
127 }
128
129 #[test]
130 fn test_display_payment() {
131 let err = Error::Payment("insufficient funds".to_string());
132 assert_eq!(err.to_string(), "payment error: insufficient funds");
133 }
134
135 #[test]
136 fn test_display_protocol() {
137 let err = Error::Protocol("invalid message".to_string());
138 assert_eq!(err.to_string(), "protocol error: invalid message");
139 }
140
141 #[test]
142 fn test_display_invalid_data() {
143 let err = Error::InvalidData("bad hash".to_string());
144 assert_eq!(err.to_string(), "invalid data: bad hash");
145 }
146
147 #[test]
148 fn test_display_serialization() {
149 let err = Error::Serialization("decode failed".to_string());
150 assert_eq!(err.to_string(), "serialization error: decode failed");
151 }
152
153 #[test]
154 fn test_display_crypto() {
155 let err = Error::Crypto("key mismatch".to_string());
156 assert_eq!(err.to_string(), "crypto error: key mismatch");
157 }
158
159 #[test]
160 fn test_display_io() {
161 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file missing");
162 let err = Error::Io(io_err);
163 assert_eq!(err.to_string(), "I/O error: file missing");
164 }
165
166 #[test]
167 fn test_display_config() {
168 let err = Error::Config("bad value".to_string());
169 assert_eq!(err.to_string(), "configuration error: bad value");
170 }
171
172 #[test]
173 fn test_display_timeout() {
174 let err = Error::Timeout("30s elapsed".to_string());
175 assert_eq!(err.to_string(), "timeout: 30s elapsed");
176 }
177
178 #[test]
179 fn test_display_insufficient_peers() {
180 let err = Error::InsufficientPeers("need 5, got 2".to_string());
181 assert_eq!(err.to_string(), "insufficient peers: need 5, got 2");
182 }
183
184 #[test]
185 fn test_display_signature_verification() {
186 let err = Error::SignatureVerification("invalid sig".to_string());
187 assert_eq!(
188 err.to_string(),
189 "signature verification failed: invalid sig"
190 );
191 }
192
193 #[test]
194 fn test_display_encryption() {
195 let err = Error::Encryption("decrypt failed".to_string());
196 assert_eq!(err.to_string(), "encryption error: decrypt failed");
197 }
198
199 #[test]
200 fn test_display_insufficient_disk_space() {
201 let err = Error::InsufficientDiskSpace("need 100 MB but only 10 MB available".to_string());
202 assert_eq!(
203 err.to_string(),
204 "insufficient disk space: need 100 MB but only 10 MB available"
205 );
206 }
207
208 #[test]
209 fn test_display_cost_estimation_inconclusive() {
210 let err = Error::CostEstimationInconclusive(
211 "sampled 5 addresses, all already stored".to_string(),
212 );
213 assert_eq!(
214 err.to_string(),
215 "cost estimation inconclusive: sampled 5 addresses, all already stored"
216 );
217 }
218
219 #[test]
220 fn test_from_io_error() {
221 let io_err = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
222 let err: Error = io_err.into();
223 assert!(matches!(err, Error::Io(_)));
224 }
225}