1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::*;
use std::ffi::{OsStr, OsString};
use std::fmt::{self, Display, Formatter};
use std::path::{Path, PathBuf};
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum Error {
NotSet(OsString),
InvalidUnicode(OsString),
}
impl Display for Error {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
fn display<'a>(var: &'a OsStr) -> impl Display + 'a { Path::new(var).display() }
if cfg!(windows) {
match self {
Error::NotSet(var) => write!(fmt, "%{}% is not set", display(var)),
Error::InvalidUnicode(var) => write!(fmt, "%{}% contains invalid unicode", display(var)),
}
} else {
match self {
Error::NotSet(var) => write!(fmt, "${{{}}} is not set", display(var)),
Error::InvalidUnicode(var) => write!(fmt, "${{{}}} contains invalid unicode", display(var)),
}
}
}
}
pub fn has_var(name: impl AsRef<OsStr> + Into<OsString>) -> bool {
std::env::var_os(name).is_some()
}
pub fn var_str(name: impl AsRef<OsStr> + Into<OsString>) -> Result<String> {
match std::env::var(name.as_ref()) {
Ok(v) => Ok(v),
Err(std::env::VarError::NotPresent) => Err(Error::NotSet(name.into())),
Err(std::env::VarError::NotUnicode(_)) => Err(Error::InvalidUnicode(name.into())),
}
}
pub fn var_lossy(name: impl AsRef<OsStr> + Into<OsString>) -> Result<String> {
match std::env::var_os(name.as_ref()) {
Some(v) => Ok(into_string_lossy(v)),
None => Err(Error::NotSet(name.into())),
}
}
pub fn var_os(name: impl AsRef<OsStr> + Into<OsString>) -> Result<OsString> {
match std::env::var_os(name.as_ref()) {
Some(v) => Ok(v),
None => Err(Error::NotSet(name.into())),
}
}
pub fn var_path(name: impl AsRef<OsStr> + Into<OsString>) -> Result<PathBuf> {
match std::env::var_os(name.as_ref()) {
Some(v) => Ok(PathBuf::from(v)),
None => Err(Error::NotSet(name.into())),
}
}
pub fn req_var_str (name: impl AsRef<OsStr> + Into<OsString>) -> String { var_str(name).or_die() }
pub fn req_var_lossy(name: impl AsRef<OsStr> + Into<OsString>) -> String { var_lossy(name).or_die() }
pub fn req_var_os (name: impl AsRef<OsStr> + Into<OsString>) -> OsString { var_os(name).or_die() }
pub fn req_var_path (name: impl AsRef<OsStr> + Into<OsString>) -> PathBuf { var_path(name).or_die() }
pub fn opt_var_str(name: impl AsRef<OsStr> + Into<OsString>) -> Result<Option<String>> {
match std::env::var(name.as_ref()) {
Ok(v) => Ok(Some(v)),
Err(std::env::VarError::NotPresent) => Ok(None),
Err(std::env::VarError::NotUnicode(_)) => Err(Error::InvalidUnicode(name.into())),
}
}
pub fn opt_var_lossy(name: impl AsRef<OsStr> + Into<OsString>) -> Option<String> {
std::env::var_os(name.as_ref()).map(into_string_lossy)
}
pub fn opt_var_os(name: impl AsRef<OsStr> + Into<OsString>) -> Option<OsString> {
std::env::var_os(name.as_ref())
}
pub fn opt_var_path(name: impl AsRef<OsStr> + Into<OsString>) -> Option<PathBuf> {
std::env::var_os(name.as_ref()).map(PathBuf::from)
}
fn into_string_lossy(os: OsString) -> String {
os.into_string().map_or_else(
|os| os.to_string_lossy().into_owned(),
|s| s,
)
}