Skip to main content

chrome_for_testing/api/
platform.rs

1use crate::error::Error;
2use crate::error::Result;
3use serde::{Deserialize, Serialize};
4use std::borrow::Cow;
5use std::env::consts;
6use std::fmt::{Display, Formatter};
7use std::str::FromStr;
8
9/// Error returned when parsing a platform string fails.
10#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
11#[error("Unknown platform: '{value}'. Expected one of: linux64, mac-arm64, mac-x64, win32, win64")]
12pub struct ParsePlatformError {
13    value: String,
14}
15
16/// Supported platforms for Chrome and `ChromeDriver` downloads.
17///
18/// This site <https://googlechromelabs.github.io/chrome-for-testing/> show the platform names
19/// defined here.
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
21pub enum Platform {
22    /// Linux x64 platform.
23    #[serde(rename = "linux64")]
24    Linux64,
25
26    /// macOS ARM64 platform (Apple Silicon).
27    #[serde(rename = "mac-arm64")]
28    MacArm64,
29
30    /// macOS x64 platform (Intel).
31    #[serde(rename = "mac-x64")]
32    MacX64,
33
34    /// Windows 32-bit platform.
35    #[serde(rename = "win32")]
36    Win32,
37
38    /// Windows 64-bit platform.
39    #[serde(rename = "win64")]
40    Win64,
41}
42
43impl Display for Platform {
44    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
45        f.write_str(match self {
46            Platform::Linux64 => "linux64",
47            Platform::MacArm64 => "mac-arm64",
48            Platform::MacX64 => "mac-x64",
49            Platform::Win32 => "win32",
50            Platform::Win64 => "win64",
51        })
52    }
53}
54
55impl FromStr for Platform {
56    type Err = ParsePlatformError;
57
58    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
59        match s {
60            "linux64" => Ok(Platform::Linux64),
61            "mac-arm64" => Ok(Platform::MacArm64),
62            "mac-x64" => Ok(Platform::MacX64),
63            "win32" => Ok(Platform::Win32),
64            "win64" => Ok(Platform::Win64),
65            _ => Err(ParsePlatformError {
66                value: s.to_owned(),
67            }),
68        }
69    }
70}
71
72impl Platform {
73    /// Detect the platform identifier that should be used for the current system.
74    ///
75    /// # Errors
76    ///
77    /// Returns an error if the current OS/architecture combination is not supported.
78    pub fn detect() -> Result<Platform> {
79        match consts::OS {
80            os @ "windows" => match consts::ARCH {
81                "x86" => Ok(Platform::Win32),
82                "x86_64" => Ok(Platform::Win64),
83                arch => Err(Error::UnsupportedPlatform {
84                    os: Cow::Borrowed(os),
85                    arch: Cow::Borrowed(arch),
86                }),
87            },
88            os @ "linux" => match consts::ARCH {
89                "x86_64" => Ok(Platform::Linux64),
90                arch => Err(Error::UnsupportedPlatform {
91                    os: Cow::Borrowed(os),
92                    arch: Cow::Borrowed(arch),
93                }),
94            },
95            os @ "macos" => match consts::ARCH {
96                "x86_64" => Ok(Platform::MacX64),
97                "arm" | "aarch64" => Ok(Platform::MacArm64),
98                arch => Err(Error::UnsupportedPlatform {
99                    os: Cow::Borrowed(os),
100                    arch: Cow::Borrowed(arch),
101                }),
102            },
103            os => Err(Error::UnsupportedPlatform {
104                os: Cow::Borrowed(os),
105                arch: Cow::Borrowed(consts::ARCH),
106            }),
107        }
108    }
109
110    /// Filename of the chrome binary.
111    #[must_use]
112    pub fn chrome_binary_name(self) -> &'static str {
113        match self {
114            Platform::Linux64 | Platform::MacX64 => "chrome",
115            Platform::MacArm64 => "Google Chrome for Testing.app",
116            Platform::Win32 | Platform::Win64 => "chrome.exe",
117        }
118    }
119
120    /// Filename of the chromedriver binary.
121    #[must_use]
122    pub fn chromedriver_binary_name(self) -> &'static str {
123        match self {
124            Platform::Linux64 | Platform::MacX64 | Platform::MacArm64 => "chromedriver",
125            Platform::Win32 | Platform::Win64 => "chromedriver.exe",
126        }
127    }
128
129    /// Tells whether this platform identifier references the Linux OS.
130    #[must_use]
131    pub fn is_linux(&self) -> bool {
132        match self {
133            Platform::Linux64 => true,
134            Platform::MacArm64 | Platform::MacX64 | Platform::Win32 | Platform::Win64 => false,
135        }
136    }
137
138    /// Tells whether this platform identifier references macOS.
139    #[must_use]
140    pub fn is_macos(&self) -> bool {
141        match self {
142            Platform::MacArm64 | Platform::MacX64 => true,
143            Platform::Linux64 | Platform::Win32 | Platform::Win64 => false,
144        }
145    }
146
147    /// Tells whether this platform identifier references the Windows OS.
148    #[must_use]
149    pub fn is_windows(&self) -> bool {
150        match self {
151            Platform::Win32 | Platform::Win64 => true,
152            Platform::Linux64 | Platform::MacArm64 | Platform::MacX64 => false,
153        }
154    }
155}
156
157#[cfg(test)]
158mod tests {
159    use super::*;
160    use assertr::prelude::*;
161
162    #[test]
163    fn parse_to_string_round_trip() {
164        let platforms = [
165            ("linux64", Platform::Linux64),
166            ("mac-arm64", Platform::MacArm64),
167            ("mac-x64", Platform::MacX64),
168            ("win32", Platform::Win32),
169            ("win64", Platform::Win64),
170        ];
171        for (s, expected) in platforms {
172            assert_that!(s.parse::<Platform>())
173                .is_ok()
174                .is_equal_to(expected);
175            assert_that!(expected.to_string()).is_equal_to(s);
176        }
177    }
178
179    #[test]
180    fn parse_invalid_variant_fails() {
181        assert_that!("Linux64".parse::<Platform>()).is_err();
182        assert_that!("unknown".parse::<Platform>()).is_err();
183    }
184
185    #[test]
186    fn serialized_value_matches_display_output() {
187        assert_that!(serde_json::to_string(&Platform::Linux64).unwrap())
188            .is_equal_to(String::from("\"linux64\""));
189        assert_that!(serde_json::to_string(&Platform::MacArm64).unwrap())
190            .is_equal_to(String::from("\"mac-arm64\""));
191    }
192}