1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Error types and error handling logic for the SDK.
use reqwest::StatusCode;
use std::io::ErrorKind;
use thiserror::Error;
/// Represents all possible errors that can occur during patching operations.
#[derive(Error, Debug)]
pub enum Error {
/// A standard I/O error occurred (e.g., file not found, permission denied).
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
/// A network error occurred during an HTTP request.
#[error("Network error: {0}")]
Network(#[from] reqwest::Error),
/// The calculated checksum of a downloaded file or chunk did not match the expected value.
#[error("Checksum mismatch! Expected {expected}, got {actual}")]
Checksum {
/// The expected MD5 hash in hex format.
expected: String,
/// The actual calculated MD5 hash in hex format.
actual: String,
},
/// A validation or parsing error occurred (e.g., invalid payload, XML syntax error).
#[error("Validation error: {0}")]
Validation(String),
}
impl From<quick_xml::DeError> for Error {
fn from(e: quick_xml::DeError) -> Self {
Self::Validation(format!("XML error: {}", e))
}
}
impl From<zip::result::ZipError> for Error {
fn from(e: zip::result::ZipError) -> Self {
Self::Validation(format!("Zip error: {}", e))
}
}
impl From<url::ParseError> for Error {
fn from(e: url::ParseError) -> Self {
Self::Validation(format!("URL parsing error: {}", e))
}
}
impl Error {
/// Determines whether the error might be resolved by retrying the operation.
pub fn is_retryable(&self) -> bool {
match self {
Error::Network(e) => {
if let Some(status) = e.status() {
status.is_server_error()
|| status == StatusCode::TOO_MANY_REQUESTS
|| status == StatusCode::REQUEST_TIMEOUT
} else {
true
}
}
Error::Checksum { .. } => true,
Error::Io(e) => matches!(
e.kind(),
ErrorKind::ConnectionAborted
| ErrorKind::ConnectionReset
| ErrorKind::ConnectionRefused
| ErrorKind::TimedOut
| ErrorKind::Interrupted
| ErrorKind::UnexpectedEof
),
Error::Validation(_) => false,
}
}
}