tact_client/
error.rs

1//! Error types for TACT client
2
3use thiserror::Error;
4
5#[derive(Error, Debug)]
6pub enum Error {
7    // Network errors
8    #[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    // Data format errors
18    #[error("BPSV parse error: {0}")]
19    Bpsv(#[from] ngdp_bpsv::Error),
20
21    #[error("Invalid manifest format at line {line}: {reason}")]
22    InvalidManifest { line: usize, reason: String },
23
24    #[error("Missing required field: {field}")]
25    MissingField { field: &'static str },
26
27    #[error("Invalid hash format: {hash}")]
28    InvalidHash { hash: String },
29
30    #[error("Checksum verification failed: expected {expected}, got {actual}")]
31    ChecksumMismatch { expected: String, actual: String },
32
33    #[error("Invalid response format")]
34    InvalidResponse,
35
36    // Configuration errors
37    #[error("Invalid region: {0}")]
38    InvalidRegion(String),
39
40    #[error("Product not supported: {0}")]
41    UnsupportedProduct(String),
42
43    #[error("Invalid protocol version")]
44    InvalidProtocolVersion,
45
46    // File errors
47    #[error("File not found: {path}")]
48    FileNotFound { path: String },
49
50    #[error("IO error: {0}")]
51    Io(#[from] std::io::Error),
52}
53
54// Helper methods for common error construction
55impl Error {
56    /// Create an invalid manifest error with line number and reason
57    pub fn invalid_manifest(line: usize, reason: impl Into<String>) -> Self {
58        Self::InvalidManifest {
59            line,
60            reason: reason.into(),
61        }
62    }
63
64    /// Create a missing field error
65    pub fn missing_field(field: &'static str) -> Self {
66        Self::MissingField { field }
67    }
68
69    /// Create a CDN exhausted error
70    pub fn cdn_exhausted(resource: impl Into<String>) -> Self {
71        Self::CdnExhausted {
72            resource: resource.into(),
73        }
74    }
75
76    /// Create a file not found error
77    pub fn file_not_found(path: impl Into<String>) -> Self {
78        Self::FileNotFound { path: path.into() }
79    }
80
81    /// Create an invalid hash error
82    pub fn invalid_hash(hash: impl Into<String>) -> Self {
83        Self::InvalidHash { hash: hash.into() }
84    }
85
86    /// Create a checksum mismatch error
87    pub fn checksum_mismatch(expected: impl Into<String>, actual: impl Into<String>) -> Self {
88        Self::ChecksumMismatch {
89            expected: expected.into(),
90            actual: actual.into(),
91        }
92    }
93}
94
95pub type Result<T> = std::result::Result<T, Error>;