ngdp_cdn/
error.rs

1//! Error types for NGDP CDN operations
2
3use thiserror::Error;
4
5/// Error types for CDN operations
6#[derive(Error, Debug)]
7pub enum Error {
8    /// HTTP request failed
9    #[error("HTTP request failed: {0}")]
10    Http(#[from] reqwest::Error),
11
12    /// Network timeout
13    #[error("Request timeout after {duration_ms}ms")]
14    Timeout {
15        /// Timeout duration in milliseconds
16        duration_ms: u64,
17    },
18
19    /// All CDN hosts exhausted
20    #[error("All CDN hosts exhausted for {resource}")]
21    CdnExhausted {
22        /// Resource being requested
23        resource: String,
24    },
25
26    /// Invalid CDN host format
27    #[error("Invalid CDN host: {host}")]
28    InvalidHost {
29        /// The invalid host string
30        host: String,
31    },
32
33    /// Invalid content hash format
34    #[error("Invalid content hash: {hash}")]
35    InvalidHash {
36        /// The invalid hash string
37        hash: String,
38    },
39
40    /// Content not found on CDN
41    #[error("Content not found: {hash}")]
42    ContentNotFound {
43        /// The content hash that was not found
44        hash: String,
45    },
46
47    /// Content verification failed
48    #[error("Content verification failed for {hash}: expected {expected}, got {actual}")]
49    VerificationFailed {
50        /// The content hash being verified
51        hash: String,
52        /// Expected checksum/hash value
53        expected: String,
54        /// Actual checksum/hash value
55        actual: String,
56    },
57
58    /// Invalid response from CDN
59    #[error("Invalid response from CDN: {reason}")]
60    InvalidResponse {
61        /// Reason for the invalid response
62        reason: String,
63    },
64
65    /// Rate limit exceeded
66    #[error("Rate limit exceeded: retry after {retry_after_secs} seconds")]
67    RateLimited {
68        /// Seconds to wait before retrying
69        retry_after_secs: u64,
70    },
71
72    /// IO error
73    #[error("IO error: {0}")]
74    Io(#[from] std::io::Error),
75
76    /// Invalid URL
77    #[error("Invalid URL: {url}")]
78    InvalidUrl {
79        /// The invalid URL
80        url: String,
81    },
82
83    /// Content size mismatch
84    #[error("Content size mismatch: expected {expected} bytes, got {actual} bytes")]
85    SizeMismatch {
86        /// Expected size in bytes
87        expected: u64,
88        /// Actual size in bytes
89        actual: u64,
90    },
91
92    /// Partial content not supported
93    #[error("CDN server does not support partial content (range requests)")]
94    PartialContentNotSupported,
95}
96
97/// Result type for CDN operations
98pub type Result<T> = std::result::Result<T, Error>;
99
100// Helper methods for common error construction
101impl Error {
102    /// Create a CDN exhausted error
103    pub fn cdn_exhausted_with_resource(resource: impl Into<String>) -> Self {
104        Self::CdnExhausted {
105            resource: resource.into(),
106        }
107    }
108
109    /// Create a CDN exhausted error with generic message
110    pub fn cdn_exhausted() -> Self {
111        Self::CdnExhausted {
112            resource: "requested content".to_string(),
113        }
114    }
115
116    /// Create an invalid host error
117    pub fn invalid_host(host: impl Into<String>) -> Self {
118        Self::InvalidHost { host: host.into() }
119    }
120
121    /// Create an invalid hash error
122    pub fn invalid_hash(hash: impl Into<String>) -> Self {
123        Self::InvalidHash { hash: hash.into() }
124    }
125
126    /// Create a content not found error
127    pub fn content_not_found(hash: impl Into<String>) -> Self {
128        Self::ContentNotFound { hash: hash.into() }
129    }
130
131    /// Create a verification failed error
132    pub fn verification_failed(
133        hash: impl Into<String>,
134        expected: impl Into<String>,
135        actual: impl Into<String>,
136    ) -> Self {
137        Self::VerificationFailed {
138            hash: hash.into(),
139            expected: expected.into(),
140            actual: actual.into(),
141        }
142    }
143
144    /// Create an invalid response error
145    pub fn invalid_response(reason: impl Into<String>) -> Self {
146        Self::InvalidResponse {
147            reason: reason.into(),
148        }
149    }
150
151    /// Create a rate limited error
152    pub fn rate_limited(retry_after_secs: u64) -> Self {
153        Self::RateLimited { retry_after_secs }
154    }
155
156    /// Create an invalid URL error
157    pub fn invalid_url(url: impl Into<String>) -> Self {
158        Self::InvalidUrl { url: url.into() }
159    }
160
161    /// Create a size mismatch error
162    pub fn size_mismatch(expected: u64, actual: u64) -> Self {
163        Self::SizeMismatch { expected, actual }
164    }
165}