use std::{path::PathBuf, process::ExitStatus};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("I/O error at {path}: {source}")]
IoWithPath {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("HTTP error: {0}")]
Http(#[from] reqwest::Error),
#[error("unexpected HTTP status: {status}")]
UnexpectedHttpStatus { status: u16 },
#[error("URL error: {0}")]
Url(#[from] url::ParseError),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("tool not found: {tool}")]
ToolNotFound { tool: String },
#[error("process failed: {program} {args:?}, status={status}, stderr={stderr}")]
ProcessFailed {
program: PathBuf,
args: Vec<String>,
status: ExitStatus,
stdout: String,
stderr: String,
},
#[error("SHA-256 mismatch for {path}: expected {expected}, got {actual}")]
HashMismatch {
path: PathBuf,
expected: String,
actual: String,
},
#[error("size mismatch for {path}: expected {expected}, got {actual}")]
SizeMismatch {
path: PathBuf,
expected: u64,
actual: u64,
},
#[error("download exceeded byte limit: limit={limit}, attempted={attempted}")]
DownloadLimitExceeded { limit: u64, attempted: u64 },
#[error(
"insufficient disk space at {path}: required={required} bytes, available={available} bytes"
)]
InsufficientDiskSpace {
path: PathBuf,
required: u64,
available: u64,
},
#[error("update manifest signature is required but missing")]
SignatureMissing,
#[error("update manifest signature public key is required")]
SignaturePublicKeyMissing,
#[error("update manifest signature verification failed")]
SignatureVerificationFailed,
#[error("invalid {kind}: {message}")]
InvalidKeyMaterial { kind: String, message: String },
#[error("unsupported patch algorithm: {0}")]
UnsupportedAlgorithm(String),
#[error("unexpected update version: expected {expected}, got {actual}")]
UnexpectedVersion { expected: String, actual: String },
#[error("invalid semantic version {value}: {message}")]
InvalidVersion { value: String, message: String },
#[error("target version must be newer than current: current={current}, target={target}")]
NonUpgradeVersion { current: String, target: String },
#[error("manifest has no platform entry for {platform}")]
MissingPlatform { platform: String },
#[error(
"no matching directory delta for platform={platform}, current_version={current_version}"
)]
NoMatchingDelta {
platform: String,
current_version: String,
},
#[error("unsupported URL or path: {0}")]
UnsupportedUrl(String),
#[error("{label} must use HTTPS in production, got {scheme}")]
InsecureTransport { label: String, scheme: String },
#[error("{0}")]
Message(String),
}
pub type Result<T> = std::result::Result<T, Error>;
pub(crate) fn io_path(path: impl Into<PathBuf>, source: std::io::Error) -> Error {
Error::IoWithPath {
path: path.into(),
source,
}
}