leyline/profile/
platform.rs1use std::collections::HashMap;
2use std::sync::LazyLock;
3
4use serde::Deserialize;
5
6use crate::tcp::TcpProfile;
7
8#[derive(Deserialize)]
9struct PlatformData {
10 tcp: TcpProfile,
11}
12
13static PLATFORMS: LazyLock<HashMap<String, PlatformData>> = LazyLock::new(|| {
14 toml::from_str(include_str!("../../profiles/platforms.toml"))
15 .expect("built-in platform table is statically valid")
16});
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19#[non_exhaustive]
20#[derive(Default)]
21pub enum Platform {
22 #[default]
23 Windows,
24 MacOS,
25 Linux,
26 Android,
27 IOS,
28 Host,
29}
30
31impl Platform {
32 pub(crate) fn detect_host() -> Self {
33 #[cfg(target_os = "windows")]
34 {
35 Self::Windows
36 }
37 #[cfg(target_os = "macos")]
38 {
39 Self::MacOS
40 }
41 #[cfg(target_os = "linux")]
42 {
43 Self::Linux
44 }
45 #[cfg(target_os = "android")]
46 {
47 Self::Android
48 }
49 #[cfg(target_os = "ios")]
50 {
51 Self::IOS
52 }
53 #[cfg(not(any(
54 target_os = "windows",
55 target_os = "macos",
56 target_os = "linux",
57 target_os = "android",
58 target_os = "ios"
59 )))]
60 {
61 Self::Windows
62 }
63 }
64
65 #[must_use]
66 pub(crate) fn resolve(self) -> Self {
67 match self {
68 Self::Host => Self::detect_host(),
69 other => other,
70 }
71 }
72
73 pub(crate) fn sec_ch_platform(&self) -> &'static str {
74 match self {
75 Self::Windows => "Windows",
76 Self::MacOS => "macOS",
77 Self::Linux => "Linux",
78 Self::Android => "Android",
79 Self::IOS => "iOS",
80 Self::Host => Self::detect_host().sec_ch_platform(),
81 }
82 }
83
84 pub(crate) fn mobile_flag(&self) -> &'static str {
85 match self {
86 Self::Android | Self::IOS => "?1",
87 Self::Host => Self::detect_host().mobile_flag(),
88 _ => "?0",
89 }
90 }
91
92 #[must_use]
93 pub fn tcp_profile(&self) -> TcpProfile {
94 PLATFORMS
95 .get(self.identity_key())
96 .map(|data| data.tcp.clone())
97 .unwrap_or_default()
98 }
99
100 bench_pub! {
101 fn identity_key(&self) -> &'static str {
102 match self {
103 Self::Windows => "windows",
104 Self::MacOS => "macos",
105 Self::Linux => "linux",
106 Self::Android => "android",
107 Self::IOS => "ios",
108 Self::Host => Self::detect_host().identity_key(),
109 }
110 }
111 }
112}
113
114impl std::fmt::Display for Platform {
115 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116 write!(f, "{}", self.sec_ch_platform())
117 }
118}