Skip to main content

hyperdb_bootstrap/
error.rs

1// Copyright (c) 2026, Salesforce, Inc. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Error types returned by the `hyperd-bootstrap` crate.
5
6use thiserror::Error;
7
8/// Errors produced while downloading, verifying, and installing `hyperd`.
9///
10/// Every fallible function in this crate returns a `Result<T, Error>`. The
11/// variants line up with the phases of bootstrap: platform detection,
12/// HTTP/curl fetching, TOML parsing, archive extraction, and checksum
13/// verification.
14#[derive(Debug, Error)]
15pub enum Error {
16    /// The host (`os` / `arch` combination) has no published `hyperd` build.
17    #[error("unsupported platform: os={os} arch={arch}")]
18    UnsupportedPlatform {
19        /// Operating-system identifier returned by `std::env::consts::OS`.
20        os: String,
21        /// Architecture identifier returned by `std::env::consts::ARCH`.
22        arch: String,
23    },
24
25    /// A platform slug (e.g. `"macos-arm64"`) did not match any known target.
26    #[error("unknown platform slug: {0}")]
27    UnknownPlatformSlug(String),
28
29    /// A filesystem or I/O operation failed, enriched with contextual text.
30    #[error("{context}: {source}")]
31    Io {
32        /// Human-readable description of the operation that was attempted.
33        context: String,
34        /// Underlying `std::io::Error` returned by the OS.
35        #[source]
36        source: std::io::Error,
37    },
38
39    /// A `reqwest` HTTP client error (connection failure, TLS issue, etc.).
40    #[error("HTTP error: {0}")]
41    Http(#[source] reqwest::Error),
42
43    /// A server returned a non-success HTTP status while fetching `url`.
44    #[error("HTTP {status} when fetching {url}")]
45    HttpStatus {
46        /// URL that was being fetched when the failure occurred.
47        url: String,
48        /// HTTP response status code.
49        status: u16,
50    },
51
52    /// The fallback `curl` subprocess exited with a non-zero status.
53    #[error("curl exited with code {code} when fetching {url}")]
54    CurlFailed {
55        /// URL passed to `curl`.
56        url: String,
57        /// `curl` exit code.
58        code: i32,
59    },
60
61    /// The downloaded archive did not match the expected SHA-256 checksum.
62    #[error("sha256 mismatch: expected {expected}, got {actual}")]
63    ChecksumMismatch {
64        /// Hex-encoded expected digest (from `hyperd-version.toml`).
65        expected: String,
66        /// Hex-encoded digest computed from the downloaded bytes.
67        actual: String,
68    },
69
70    /// The `hyperd-version.toml` file could not be parsed.
71    #[error("failed to parse version TOML: {0}")]
72    TomlParse(#[source] toml::de::Error),
73
74    /// The downloaded ZIP archive was malformed or could not be extracted.
75    #[error("zip error: {0}")]
76    Zip(#[source] zip::result::ZipError),
77
78    /// The archive did not contain a recognizable `hyperd` executable.
79    #[error("hyperd executable not found in extracted archive")]
80    HyperdNotInArchive,
81
82    /// Scraping the public releases page for the latest version failed.
83    #[error("failed to scrape latest release: {0}")]
84    ScrapeFailed(&'static str),
85}
86
87impl Error {
88    /// Constructs an [`Self::UnsupportedPlatform`] error.
89    pub fn unsupported_platform(os: impl Into<String>, arch: impl Into<String>) -> Self {
90        Error::UnsupportedPlatform {
91            os: os.into(),
92            arch: arch.into(),
93        }
94    }
95
96    /// Constructs an [`Self::UnknownPlatformSlug`] error.
97    pub fn unknown_platform_slug(slug: impl Into<String>) -> Self {
98        Error::UnknownPlatformSlug(slug.into())
99    }
100
101    /// Constructs an [`Self::Io`] error.
102    pub fn io(context: impl Into<String>, source: std::io::Error) -> Self {
103        Error::Io {
104            context: context.into(),
105            source,
106        }
107    }
108
109    /// Constructs an [`Self::HttpStatus`] error.
110    pub fn http_status(url: impl Into<String>, status: u16) -> Self {
111        Error::HttpStatus {
112            url: url.into(),
113            status,
114        }
115    }
116
117    /// Constructs an [`Self::CurlFailed`] error.
118    pub fn curl_failed(url: impl Into<String>, code: i32) -> Self {
119        Error::CurlFailed {
120            url: url.into(),
121            code,
122        }
123    }
124
125    /// Constructs an [`Self::ChecksumMismatch`] error.
126    pub fn checksum_mismatch(expected: impl Into<String>, actual: impl Into<String>) -> Self {
127        Error::ChecksumMismatch {
128            expected: expected.into(),
129            actual: actual.into(),
130        }
131    }
132}