1use thiserror::Error;
4
5#[derive(Error, Debug)]
6pub enum Error {
7 #[error("HTTP request failed: {0}")]
9 Http(#[from] reqwest::Error),
10
11 #[error("All CDN hosts exhausted for {resource}")]
12 CdnExhausted { resource: String },
13
14 #[error("Connection timeout to {host}")]
15 ConnectionTimeout { host: String },
16
17 #[error("BPSV parse error: {0}")]
19 Bpsv(#[from] ngdp_bpsv::Error),
20
21 #[error("JSON serialization/deserialization error: {0}")]
22 Json(#[from] serde_json::Error),
23
24 #[error("Invalid manifest format at line {line}: {reason}")]
25 InvalidManifest { line: usize, reason: String },
26
27 #[error("Missing required field: {field}")]
28 MissingField { field: &'static str },
29
30 #[error("Invalid hash format: {hash}")]
31 InvalidHash { hash: String },
32
33 #[error("Checksum verification failed: expected {expected}, got {actual}")]
34 ChecksumMismatch { expected: String, actual: String },
35
36 #[error("Invalid response format")]
37 InvalidResponse,
38
39 #[error("Invalid region: {0}")]
41 InvalidRegion(String),
42
43 #[error("Product not supported: {0}")]
44 UnsupportedProduct(String),
45
46 #[error("Invalid protocol version")]
47 InvalidProtocolVersion,
48
49 #[error("File not found: {path}")]
51 FileNotFound { path: String },
52
53 #[error("IO error: {0}")]
54 Io(#[from] std::io::Error),
55}
56
57impl Error {
59 pub fn invalid_manifest(line: usize, reason: impl Into<String>) -> Self {
61 Self::InvalidManifest {
62 line,
63 reason: reason.into(),
64 }
65 }
66
67 pub fn missing_field(field: &'static str) -> Self {
69 Self::MissingField { field }
70 }
71
72 pub fn cdn_exhausted(resource: impl Into<String>) -> Self {
74 Self::CdnExhausted {
75 resource: resource.into(),
76 }
77 }
78
79 pub fn file_not_found(path: impl Into<String>) -> Self {
81 Self::FileNotFound { path: path.into() }
82 }
83
84 pub fn invalid_hash(hash: impl Into<String>) -> Self {
86 Self::InvalidHash { hash: hash.into() }
87 }
88
89 pub fn checksum_mismatch(expected: impl Into<String>, actual: impl Into<String>) -> Self {
91 Self::ChecksumMismatch {
92 expected: expected.into(),
93 actual: actual.into(),
94 }
95 }
96}
97
98pub type Result<T> = std::result::Result<T, Error>;