relay_knowledge/env/
platform.rs1use std::{env as process_env, ffi::OsString};
4
5use super::{
6 EnvError,
7 value_parser::{EnvironmentValues, first_path_var, path_var},
8};
9
10pub(super) const HOME: &str = "HOME";
11const WINDOWS_SYSTEM_ROOT: &str = "SystemRoot";
12const XDG_CONFIG_HOME: &str = "XDG_CONFIG_HOME";
13const XDG_DATA_HOME: &str = "XDG_DATA_HOME";
14const XDG_STATE_HOME: &str = "XDG_STATE_HOME";
15const XDG_CACHE_HOME: &str = "XDG_CACHE_HOME";
16const XDG_RUNTIME_DIR: &str = "XDG_RUNTIME_DIR";
17const APPDATA: &str = "APPDATA";
18const LOCALAPPDATA: &str = "LOCALAPPDATA";
19pub(super) const TMPDIR: &str = "TMPDIR";
20pub(super) const TEMP: &str = "TEMP";
21pub(super) const TMP: &str = "TMP";
22
23pub(crate) fn windows_system_root_from_process() -> Option<OsString> {
24 process_env::var_os(WINDOWS_SYSTEM_ROOT).filter(|value| !value.is_empty())
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum PlatformKind {
30 Unix,
31 Macos,
32 Windows,
33 Other,
34}
35
36impl PlatformKind {
37 pub const fn current() -> Self {
39 if cfg!(target_os = "windows") {
40 Self::Windows
41 } else if cfg!(target_os = "macos") {
42 Self::Macos
43 } else if cfg!(unix) {
44 Self::Unix
45 } else {
46 Self::Other
47 }
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq)]
53pub struct PlatformEnvironment {
54 pub platform: PlatformKind,
55 pub home_dir: Option<std::path::PathBuf>,
56 pub xdg_config_home: Option<std::path::PathBuf>,
57 pub xdg_data_home: Option<std::path::PathBuf>,
58 pub xdg_state_home: Option<std::path::PathBuf>,
59 pub xdg_cache_home: Option<std::path::PathBuf>,
60 pub xdg_runtime_dir: Option<std::path::PathBuf>,
61 pub app_data: Option<std::path::PathBuf>,
62 pub local_app_data: Option<std::path::PathBuf>,
63 pub temp_dir: Option<std::path::PathBuf>,
64}
65
66pub(super) fn platform_environment(
67 values: &EnvironmentValues,
68 platform: PlatformKind,
69) -> Result<PlatformEnvironment, EnvError> {
70 let temp_variables: &[&'static str] = if platform == PlatformKind::Windows {
71 &[TEMP, TMP, TMPDIR]
72 } else {
73 &[TMPDIR, TEMP, TMP]
74 };
75
76 Ok(PlatformEnvironment {
77 platform,
78 home_dir: path_var(values, HOME)?,
79 xdg_config_home: path_var(values, XDG_CONFIG_HOME)?,
80 xdg_data_home: path_var(values, XDG_DATA_HOME)?,
81 xdg_state_home: path_var(values, XDG_STATE_HOME)?,
82 xdg_cache_home: path_var(values, XDG_CACHE_HOME)?,
83 xdg_runtime_dir: path_var(values, XDG_RUNTIME_DIR)?,
84 app_data: path_var(values, APPDATA)?,
85 local_app_data: path_var(values, LOCALAPPDATA)?,
86 temp_dir: first_path_var(values, temp_variables)?,
87 })
88}
89
90pub(super) fn normalize_key(platform: PlatformKind, key: OsString) -> OsString {
91 if platform == PlatformKind::Windows {
92 key.to_str()
93 .map(|value| OsString::from(value.to_ascii_uppercase()))
94 .unwrap_or(key)
95 } else {
96 key
97 }
98}
99
100#[cfg(test)]
101#[path = "platform_tests.rs"]
102mod platform_tests;