use crate::error::Error;
use hex_literal::hex;
use std::fmt::Display;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum OS {
Linux,
#[expect(
clippy::upper_case_acronyms,
reason = "OSX is a permitted all-caps acronym"
)]
OSX,
}
impl OS {
#[must_use]
pub fn current() -> Self {
match std::env::consts::OS {
"linux" => Self::Linux,
"macos" => Self::OSX,
unsupported_os => panic!("unsupported OS: {unsupported_os}"),
}
}
#[must_use]
pub const fn all() -> &'static [Self] {
&[Self::Linux, Self::OSX]
}
#[must_use]
pub const fn rust_identifier(self) -> &'static str {
match self {
Self::Linux => "Linux",
Self::OSX => "OSX",
}
}
}
impl Display for OS {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Linux => "linux",
Self::OSX => "osx",
};
write!(f, "{s}")
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum CPUArch {
#[allow(clippy::doc_markdown)]
AArch64,
#[allow(clippy::doc_markdown)]
X86_64,
}
impl CPUArch {
#[must_use]
pub fn current() -> Self {
match std::env::consts::ARCH {
"aarch64" => Self::AArch64,
"x86_64" => Self::X86_64,
unsupported_arch => panic!("unsupported arch: {unsupported_arch}"),
}
}
#[must_use]
pub const fn all() -> &'static [Self] {
&[Self::AArch64, Self::X86_64]
}
#[must_use]
pub const fn code_label(self) -> &'static str {
match self {
Self::AArch64 => "AArch64",
Self::X86_64 => "X86_64",
}
}
}
impl Display for CPUArch {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::AArch64 => "aarch_64",
Self::X86_64 => "x86_64",
};
write!(f, "{s}")
}
}
type Sha256HashResult = [u8; 32];
struct KnownVersion {
os: OS,
cpu: CPUArch,
version: &'static str,
hash: Sha256HashResult,
}
pub const LATEST_VERSION: &str = KNOWN_VERSIONS[KNOWN_VERSIONS.len() - 1].version;
pub fn known_hash(os: OS, cpu: CPUArch, version: &str) -> Result<Sha256HashResult, Error> {
for known in KNOWN_VERSIONS {
if known.os == os && known.cpu == cpu && known.version == version {
return Ok(known.hash);
}
}
Err(Error::from_string(format!(
"unknown hash for {os} {cpu} {version}"
)))
}
const KNOWN_VERSIONS: &[KnownVersion] = &[
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "27.0",
hash: hex!("e2bdce49564dbad4676023d174d9cdcf932238bc0b56a8349a5cb27bbafc26b0"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "27.0",
hash: hex!("1e4b2d8b145afe99a36602f305165761e46d2525aa94cbb907e2e983be6717ac"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "27.1",
hash: hex!("8809c2ec85368c6b6e9af161b6771a153aa92670a24adbe46dd34fa02a04df2f"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "27.1",
hash: hex!("8970e3d8bbd67d53768fe8c2e3971bdd71e51cfe2001ca06dacad17258a7dae3"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "27.1",
hash: hex!("03b7af1bf469e7285dc51976ee5fa99412704dbd1c017105114852a37b165c12"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "27.1",
hash: hex!("8520d944f3a3890fa296a3b3b0d4bb18337337e2526bbbf1b507eeea3c2a1ec4"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "27.2",
hash: hex!("ff4760bd4ae510d533e528cc6deb8e32e53f383f0ec01b0327233b4c2e8db314"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "27.2",
hash: hex!("4a95e0ea2e51720af86a92f48d4997c8756923a9d0c58fd8a850657cd7479caf"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "27.2",
hash: hex!("877de17b5d2662b96e68a6e208cb1851437ab3e2b419c2ef5b7b873ffac5357d"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "27.2",
hash: hex!("abc25a236571612d45eb4b6b6e6abe3ac9aecc34b195f76f248786844f5619c7"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "27.3",
hash: hex!("bdad36f3ad7472281d90568c4956ea2e203c216e0de005c6bd486f1920f2751c"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "27.3",
hash: hex!("6dab2adab83f915126cab53540d48957c40e9e9023969c3e84d44bfb936c7741"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "27.3",
hash: hex!("b22116bd97cdbd7ea25346abe635a9df268515fe5ef5afa93cd9a68fc2513f84"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "27.3",
hash: hex!("ce282648fed0e7fbd6237d606dc9ec168dd2c1863889b04efa0b19c47da65d1b"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "28.2",
hash: hex!("91d8253cdc0f0f0fc51c2b69c80677996632f525ad84504bfa5b4ee38ad3e49c"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "28.2",
hash: hex!("2febfd42b59ce93a28eb789019a470a3dd0449619bc04f84dad1333da261dec1"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "28.2",
hash: hex!("7bb048f52841789d9ec61983be0ce4c9e4fb3bd9a143462820ba9a3be0a03797"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "28.2",
hash: hex!("232f07d12bf4806207a79ec2c7378301c52e6f2f7efdd21c0dd416f0bda103ec"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "29.0",
hash: hex!("305f1be5ae7b2f39451870b312b45c1e0ba269901c83ba16d85f9f9d1441b348"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "29.0",
hash: hex!("3c51065af3b9a606d9e18a1bf628143734ff4b9e69725d6459857430ba7a78df"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "29.0",
hash: hex!("b2b59f03b030c8a748623d682a8b5bc9cc099e4bcfd06b8964ce89ec065b3103"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "29.0",
hash: hex!("e7a1cffc82e21daa67833011449c70ddff1eba3b115934387e6e8141efab092f"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "29.2",
hash: hex!("29cf483e2fb21827e5fac4964e35eae472a238e28c762f02fb17dcd93ff8b89f"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "29.2",
hash: hex!("52e9e7ece55c7e30e7e8bbd254b4b21b408a5309bca826763c7124b696a132e9"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "29.2",
hash: hex!("0e153a38d6da19594c980e7f7cd3ea0ddd52c9da1068c03c0d8533369fbfeb20"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "29.2",
hash: hex!("ba2bd983b5f06ec38d663b602884a597dea3990a43803d7e153ed8f7c54269e1"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "29.3",
hash: hex!("6427349140e01f06e049e707a58709a4f221ae73ab9a0425bc4a00c8d0e1ab32"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "29.3",
hash: hex!("3e866620c5be27664f3d2fa2d656b5f3e09b5152b42f1bedbf427b333e90021a"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "29.3",
hash: hex!("2b8a3403cd097f95f3ba656e14b76c732b6b26d7f183330b11e36ef2bc028765"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "29.3",
hash: hex!("9a788036d8f9854f7b03c305df4777cf0e54e5b081e25bf15252da87e0e90875"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "30.0",
hash: hex!("5ab347b71fb8a87139cec36aac4bd0ee3ac3f4f2af9fc68ebdf556e1c0a665c6"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "30.0",
hash: hex!("2fbbc1818463d7e6d93c19a8dea839e663ca5f8579a52ef78c7688188335fa6c"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "30.0",
hash: hex!("7eb5b51d37bac410ba70ef91c404f90b1fabcb823712ff656582d34acc87ca74"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "30.0",
hash: hex!("96bf3a5fbeefd57d7dc0c20a2c7bb3f226ad84b79e5b509386824322017b9417"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "30.1",
hash: hex!("e866d3dc4775e8032721915e83e3fb6e1ab4def7199a49b4f95c4d1f6cf4c03a"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "30.1",
hash: hex!("5537e15ab0c0e610f809573948d3ec7d6ef387a07991e1c361a2a0e8cad983e5"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "30.1",
hash: hex!("03467cfd967de12a61406b7473e80204d3ae38f30f82855318186d696237e3b9"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "30.1",
hash: hex!("a4aeefd2f59ccce59cfa01a89fe58adb40bb9010f43adfca3c4fee7fd37ec2c5"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "30.2",
hash: hex!("a3173ea338ef91b1605b88c4f8120d6c8ccf36f744d9081991d595d0d4352996"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "30.2",
hash: hex!("327e9397c6fb3ea2a542513a3221334c6f76f7aa524a7d2561142b67b312a01f"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "30.2",
hash: hex!("92728c650f6cf2b6c37891ae04ef5bc2d4b5f32c5fbbd101eda623f90bb95f63"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "30.2",
hash: hex!("65675c3bb874a2d5f0c941e61bce6175090be25fe466f0ec2d4a6f5978333624"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "31.0",
hash: hex!("999f4c023366b0b68c5c65272ead7877e47a2670245a79904b83450575da7e19"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "31.0",
hash: hex!("24e2ed32060b7c990d5eb00d642fde04869d7f77c6d443f609353f097799dd42"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "31.0",
hash: hex!("1fbe70a8d646875f91b6fd57294f763145292b2c9e1374ab09d6e2124afdd950"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "31.0",
hash: hex!("0360d9b6d9e3d66958cf6274d8514da49e76d475fd0d712181dcc7e9e056f2c8"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "31.1",
hash: hex!("6c554de11cea04c56ebf8e45b54434019b1cd85223d4bbd25c282425e306ecc2"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "31.1",
hash: hex!("96553041f1a91ea0efee963cb16f462f5985b4d65365f3907414c360044d8065"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "31.1",
hash: hex!("4aeea0a34b0992847b03a8489a8dbedf3746de01109b74cc2ce9b6888a901ed9"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "31.1",
hash: hex!("485e87088b18614c25a99b1c0627918b3ff5b9fde54922fb1c920159fab7ba29"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "33.0",
hash: hex!("4b96bc91f8b54d829b8c3ca2207ff1ceb774843321e4fa5a68502faece584272"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "33.0",
hash: hex!("d99c011b799e9e412064244f0be417e5d76c9b6ace13a2ac735330fa7d57ad8f"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "33.0",
hash: hex!("3cf55dd47118bd2efda9cd26b74f8bbbfcf5beb1bf606bc56ad4c001b543f6d3"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "33.0",
hash: hex!("e4e50a703147a92d1a5a2d3a34c9e41717f67ade67d4be72b9a466eb8f22fe87"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "33.2",
hash: hex!("706662a332683aa2fffe1c4ea61588279d31679cd42d91c7d60a69651768edb8"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "33.2",
hash: hex!("b24b53f87c151bfd48b112fe4c3a6e6574e5198874f38036aff41df3456b8caf"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "33.2",
hash: hex!("5be1427127788c9f7dd7d606c3e69843dd3587327dea993917ffcb77e7234b44"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "33.2",
hash: hex!("dba51cfcc85076d56e7de01a647865c5a7f995c3dce427d5215b53e50b7be43f"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "33.5",
hash: hex!("2b0fcf9b2c32cbadccc0eb7a88b841fffecd4a06fc80acdba2b5be45e815c38a"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "33.5",
hash: hex!("24e58fb231d50306ee28491f33a170301e99540f7e29ca461e0e80fd1239f8d1"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "33.5",
hash: hex!("7084c6482e3bb416a33fe2162ba566711773b842e6953bf6cb181647b9ef57c0"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "33.5",
hash: hex!("7f31625f8bec4929082ae9209e101c1c03692624457cc6332f83736db495ee92"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "34.0",
hash: hex!("f0b8aad28be5ea6150c082f96ac57e028154afb9ee29f4ce092b5a39df8ae6c8"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "34.0",
hash: hex!("e9a91b6fcfe4177ec2cd35fc8f15c1e811fa0ecdef9372755cd6d3513d5faaab"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "34.0",
hash: hex!("3ef35187a3c8aed81ee57e792227e483e558fa56c93fce525e569bff55794c1a"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "34.0",
hash: hex!("d58fcd413a9ed458283d54023e409fd5cf767da4ed225d1ffaffd83cf2764f53"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::AArch64,
version: "34.1",
hash: hex!("31c5e9e3c7bf013cf41fb97765ee255c140024a6b175b6cc9b64beddd7c23ba7"),
},
KnownVersion {
os: OS::Linux,
cpu: CPUArch::X86_64,
version: "34.1",
hash: hex!("af27ea66cd26938fe48587804ca7d4817457a08350021a1c6e23a27ccc8c6904"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::AArch64,
version: "34.1",
hash: hex!("2c7e92b8b578916937df132b3032e2e8e6c170862ecf7a8333094a6f3d03650c"),
},
KnownVersion {
os: OS::OSX,
cpu: CPUArch::X86_64,
version: "34.1",
hash: hex!("ab124429c1f49951f03b6c0c0e911fec04e2c7c20de5c935e0cde7353bbd016c"),
},
];
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use super::*;
#[test]
fn test_known_hash() {
known_hash(OS::current(), CPUArch::current(), LATEST_VERSION).unwrap();
}
#[test]
fn test_known_versions_constant() {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
struct KnownVersionKey {
os: OS,
cpu: CPUArch,
version: String,
}
let mut all_versions = HashSet::new();
let mut last_version = KNOWN_VERSIONS[0].version;
for known_version in KNOWN_VERSIONS {
assert!(known_version.version >= last_version);
last_version = known_version.version;
let key = KnownVersionKey {
os: known_version.os,
cpu: known_version.cpu,
version: known_version.version.to_string(),
};
let newly_inserted = all_versions.insert(key.clone());
assert!(newly_inserted, "duplicate version: {key:?}");
}
assert_eq!(LATEST_VERSION, last_version);
}
}