1use std::ffi::OsString;
2
3use crate::{
4 fallible,
5 os::{Os, Target},
6 Arch, DesktopEnv, Language, Platform, Result,
7};
8
9macro_rules! report_message {
10 () => {
11 "Please report this issue at https://github.com/ardaku/whoami/issues"
12 };
13}
14
15const DEFAULT_USERNAME: &str = "Unknown";
16const DEFAULT_HOSTNAME: &str = "LocalHost";
17
18#[inline(always)]
20pub fn arch() -> Arch {
21 Target::arch(Os).expect(concat!("arch() failed. ", report_message!()))
22}
23
24#[inline(always)]
29pub fn username() -> String {
30 fallible::username().unwrap_or_else(|_| DEFAULT_USERNAME.to_lowercase())
31}
32
33#[inline(always)]
38pub fn username_os() -> OsString {
39 fallible::username_os()
40 .unwrap_or_else(|_| DEFAULT_USERNAME.to_lowercase().into())
41}
42
43#[inline(always)]
45pub fn realname() -> String {
46 fallible::realname()
47 .or_else(|_| fallible::username())
48 .unwrap_or_else(|_| DEFAULT_USERNAME.to_owned())
49}
50
51#[inline(always)]
53pub fn realname_os() -> OsString {
54 fallible::realname_os()
55 .or_else(|_| fallible::username_os())
56 .unwrap_or_else(|_| DEFAULT_USERNAME.to_owned().into())
57}
58
59#[inline(always)]
63pub fn devicename() -> String {
64 fallible::devicename()
65 .or_else(|_| fallible::hostname())
66 .unwrap_or_else(|_| DEFAULT_HOSTNAME.to_string())
67}
68
69#[inline(always)]
73pub fn devicename_os() -> OsString {
74 fallible::devicename_os()
75 .or_else(|_| fallible::hostname().map(OsString::from))
76 .unwrap_or_else(|_| DEFAULT_HOSTNAME.to_string().into())
77}
78
79#[inline(always)]
88#[deprecated(note = "use `fallible::hostname()` instead", since = "1.5.0")]
89pub fn hostname() -> String {
90 let mut hostname = fallible::hostname()
91 .unwrap_or_else(|_| DEFAULT_HOSTNAME.to_lowercase());
92
93 hostname.make_ascii_lowercase();
94 hostname
95}
96
97#[inline(always)]
106#[deprecated(note = "use `fallible::hostname()` instead", since = "1.5.0")]
107pub fn hostname_os() -> OsString {
108 #[allow(deprecated)]
109 hostname().into()
110}
111
112#[inline(always)]
116pub fn distro() -> String {
117 fallible::distro().unwrap_or_else(|_| format!("Unknown {}", platform()))
118}
119
120#[inline(always)]
124#[deprecated(note = "use `distro()` instead", since = "1.5.0")]
125pub fn distro_os() -> OsString {
126 fallible::distro()
127 .map(OsString::from)
128 .unwrap_or_else(|_| format!("Unknown {}", platform()).into())
129}
130
131#[inline(always)]
135pub fn desktop_env() -> DesktopEnv {
136 Target::desktop_env(Os)
137}
138
139#[inline(always)]
141pub fn platform() -> Platform {
142 Target::platform(Os)
143}
144
145#[inline(always)]
151#[deprecated(note = "use `langs()` instead", since = "1.5.0")]
152pub fn lang() -> impl Iterator<Item = String> {
153 let langs_vec = if let Ok(langs) = langs() {
154 langs
155 .map(|lang| lang.to_string().replace('/', "-"))
156 .collect()
157 } else {
158 ["en-US".to_string()].to_vec()
159 };
160
161 langs_vec.into_iter()
162}
163
164#[inline(always)]
170pub fn langs() -> Result<impl Iterator<Item = Language>> {
171 let langs = Target::langs(Os)?;
173 let langs = langs
174 .split(';')
175 .map(ToString::to_string)
176 .collect::<Vec<_>>();
177
178 Ok(langs.into_iter().filter_map(|lang| {
179 let lang = lang
180 .split_terminator('.')
181 .next()
182 .unwrap_or_default()
183 .replace(|x| ['_', '-'].contains(&x), "/");
184
185 if lang == "C" {
186 return None;
187 }
188
189 Some(Language::__(Box::new(lang)))
190 }))
191}