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)]
104#[deprecated(note = "use `fallible::hostname()` instead", since = "1.5.0")]
105pub fn hostname_os() -> OsString {
106 #[allow(deprecated)]
107 hostname().into()
108}
109
110#[inline(always)]
114pub fn distro() -> String {
115 fallible::distro().unwrap_or_else(|_| format!("Unknown {}", platform()))
116}
117
118#[inline(always)]
122#[deprecated(note = "use `distro()` instead", since = "1.5.0")]
123pub fn distro_os() -> OsString {
124 fallible::distro()
125 .map(OsString::from)
126 .unwrap_or_else(|_| format!("Unknown {}", platform()).into())
127}
128
129#[inline(always)]
133pub fn desktop_env() -> DesktopEnv {
134 Target::desktop_env(Os)
135}
136
137#[inline(always)]
139pub fn platform() -> Platform {
140 Target::platform(Os)
141}
142
143#[inline(always)]
149#[deprecated(note = "use `langs()` instead", since = "1.5.0")]
150pub fn lang() -> impl Iterator<Item = String> {
151 let langs_vec = if let Ok(langs) = langs() {
152 langs
153 .map(|lang| lang.to_string().replace('/', "-"))
154 .collect()
155 } else {
156 ["en-US".to_string()].to_vec()
157 };
158
159 langs_vec.into_iter()
160}
161
162#[inline(always)]
168pub fn langs() -> Result<impl Iterator<Item = Language>> {
169 let langs = Target::langs(Os)?;
171 let langs = langs
172 .split(':')
173 .map(ToString::to_string)
174 .filter_map(|lang| {
175 let lang = lang
176 .split_terminator('.')
177 .next()
178 .unwrap_or_default()
179 .replace(|x| ['_', '-'].contains(&x), "/");
180
181 if lang == "C" {
182 return None;
183 }
184
185 Some(Language::__(Box::new(lang)))
186 });
187
188 Ok(langs.collect::<Vec<_>>().into_iter())
189}