1#![allow(unsafe_code)]
2
3#[cfg_attr(all(target_arch = "wasm32", daku), path = "os/daku.rs")]
5#[cfg_attr(
7 all(target_os = "redox", not(target_arch = "wasm32")),
8 path = "os/redox.rs"
9)]
10#[cfg_attr(
12 all(
13 any(
14 target_os = "linux",
15 target_os = "macos",
16 target_os = "dragonfly",
17 target_os = "freebsd",
18 target_os = "netbsd",
19 target_os = "openbsd",
20 target_os = "illumos",
21 target_os = "hurd",
22 ),
23 not(target_arch = "wasm32")
24 ),
25 path = "os/unix.rs"
26)]
27#[cfg_attr(
29 all(target_arch = "wasm32", target_os = "wasi"),
30 path = "os/wasi.rs"
31)]
32#[cfg_attr(
34 all(
35 target_arch = "wasm32",
36 not(target_os = "wasi"),
37 not(daku),
38 feature = "web",
39 ),
40 path = "os/web.rs"
41)]
42#[cfg_attr(
44 all(target_os = "windows", not(target_arch = "wasm32")),
45 path = "os/windows.rs"
46)]
47mod target;
48
49use std::{
50 env::{self, VarError},
51 ffi::OsString,
52 io::{Error, ErrorKind},
53};
54
55use crate::{Arch, DesktopEnv, Platform, Result};
56
57pub(crate) struct Os;
59
60pub(crate) trait Target: Sized {
62 fn langs(self) -> Result<String>;
64 fn realname(self) -> Result<OsString>;
66 fn username(self) -> Result<OsString>;
68 fn devicename(self) -> Result<OsString>;
70 fn hostname(self) -> Result<String>;
72 fn distro(self) -> Result<String>;
74 fn desktop_env(self) -> DesktopEnv;
76 fn platform(self) -> Platform;
78 fn arch(self) -> Result<Arch>;
80
81 fn account(self) -> Result<OsString> {
84 self.username()
85 }
86}
87
88#[allow(dead_code)]
90fn err_missing_record() -> Error {
91 Error::new(ErrorKind::NotFound, "Missing record")
92}
93
94#[allow(dead_code)]
96fn err_null_record() -> Error {
97 Error::new(ErrorKind::NotFound, "Null record")
98}
99
100#[allow(dead_code)]
102fn err_empty_record() -> Error {
103 Error::new(ErrorKind::NotFound, "Empty record")
104}
105
106#[allow(dead_code)]
108fn unix_lang() -> Result<String> {
109 let check_var = |var| {
110 env::var(var).map_err(|e| {
111 let kind = match e {
112 VarError::NotPresent => ErrorKind::NotFound,
113 VarError::NotUnicode(_) => ErrorKind::InvalidData,
114 };
115 Error::new(kind, e)
116 })
117 };
118
119 let locale = check_var("LC_ALL").or_else(|_| check_var("LANG"));
122
123 let langs = match &locale {
127 Ok(loc) if loc != "C" => check_var("LANGUAGE").or(locale),
128 _ => locale,
129 }?;
130
131 if langs.is_empty() {
132 return Err(err_empty_record());
133 }
134
135 Ok(langs)
136}