Skip to main content

hyperdb_bootstrap/
platform.rs

1// Copyright (c) 2026, Salesforce, Inc. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Host-platform detection and slug encoding for the four targets that
5//! Tableau's Hyper API ships binaries for.
6
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10use crate::Error;
11
12/// One of the four platforms that Tableau publishes a `hyperd` build for.
13///
14/// The variant names encode both OS and architecture and map 1:1 to the
15/// slugs used in the release URL structure and in `hyperd-version.toml`.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
17#[serde(rename_all = "kebab-case")]
18pub enum Platform {
19    /// Apple Silicon macOS (`aarch64-apple-darwin`).
20    #[serde(rename = "macos-arm64")]
21    MacosArm64,
22    /// Intel macOS (`x86_64-apple-darwin`).
23    #[serde(rename = "macos-x86_64")]
24    MacosX86_64,
25    /// 64-bit Linux (`x86_64-unknown-linux-gnu`).
26    #[serde(rename = "linux-x86_64")]
27    LinuxX86_64,
28    /// 64-bit Windows (`x86_64-pc-windows-msvc`).
29    #[serde(rename = "windows-x86_64")]
30    WindowsX86_64,
31}
32
33impl Platform {
34    /// Detects the current host's platform.
35    ///
36    /// Uses `std::env::consts::OS` and `std::env::consts::ARCH`. Returns
37    /// [`Error::UnsupportedPlatform`] for any combination that has no
38    /// published `hyperd` build.
39    ///
40    /// # Errors
41    ///
42    /// Returns [`Error::UnsupportedPlatform`] when the host OS/arch pair
43    /// does not match one of the four supported targets.
44    pub fn current() -> Result<Self, Error> {
45        let os = std::env::consts::OS;
46        let arch = std::env::consts::ARCH;
47        match (os, arch) {
48            ("macos", "aarch64") => Ok(Self::MacosArm64),
49            ("macos", "x86_64") => Ok(Self::MacosX86_64),
50            ("linux", "x86_64") => Ok(Self::LinuxX86_64),
51            ("windows", "x86_64") => Ok(Self::WindowsX86_64),
52            _ => Err(Error::unsupported_platform(os, arch)),
53        }
54    }
55
56    /// Returns the kebab-case slug used in release URLs and version metadata
57    /// (for example, `"macos-arm64"`).
58    #[must_use]
59    pub fn slug(self) -> &'static str {
60        match self {
61            Self::MacosArm64 => "macos-arm64",
62            Self::MacosX86_64 => "macos-x86_64",
63            Self::LinuxX86_64 => "linux-x86_64",
64            Self::WindowsX86_64 => "windows-x86_64",
65        }
66    }
67
68    /// Returns the file name of the `hyperd` executable on this platform
69    /// (`"hyperd.exe"` on Windows, `"hyperd"` elsewhere).
70    #[must_use]
71    pub fn executable_name(self) -> &'static str {
72        match self {
73            Self::WindowsX86_64 => "hyperd.exe",
74            _ => "hyperd",
75        }
76    }
77}
78
79impl fmt::Display for Platform {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        f.write_str(self.slug())
82    }
83}
84
85impl std::str::FromStr for Platform {
86    type Err = Error;
87
88    fn from_str(s: &str) -> Result<Self, Self::Err> {
89        match s {
90            "macos-arm64" => Ok(Self::MacosArm64),
91            "macos-x86_64" => Ok(Self::MacosX86_64),
92            "linux-x86_64" => Ok(Self::LinuxX86_64),
93            "windows-x86_64" => Ok(Self::WindowsX86_64),
94            other => Err(Error::unknown_platform_slug(other)),
95        }
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[test]
104    fn slug_roundtrip() {
105        for p in [
106            Platform::MacosArm64,
107            Platform::MacosX86_64,
108            Platform::LinuxX86_64,
109            Platform::WindowsX86_64,
110        ] {
111            assert_eq!(p.slug().parse::<Platform>().unwrap(), p);
112        }
113    }
114
115    #[test]
116    fn executable_name_windows() {
117        assert_eq!(Platform::WindowsX86_64.executable_name(), "hyperd.exe");
118        assert_eq!(Platform::LinuxX86_64.executable_name(), "hyperd");
119    }
120}