Skip to content

Commit 7f32505

Browse files
committed
Override count, nth and last for sys::windows::os::Env
Avoids doing the [u16] -> OsString conversion when we don't care about using the env vars.
1 parent 8aa512d commit 7f32505

File tree

1 file changed

+39
-9
lines changed
  • src/libstd/sys/windows

1 file changed

+39
-9
lines changed

src/libstd/sys/windows/os.rs

+39-9
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,23 @@ pub fn error_string(errnum: i32) -> String {
7272
}
7373

7474
pub struct Env {
75+
inner: EnvSlices,
76+
}
77+
78+
// This is a sub-iterator for `Env` to avoid allocating `OsString`s when not
79+
// needed, by separating the iteration over the `LPWCH` from constructing the
80+
// result strings this allows methods on `Env` such as `nth` to avoid allocations.
81+
struct EnvSlices {
7582
base: c::LPWCH,
7683
cur: c::LPWCH,
7784
}
7885

79-
impl Iterator for Env {
80-
type Item = (OsString, OsString);
86+
impl Iterator for EnvSlices {
87+
// These aren't really 'static, but that's required to avoid some unwanted
88+
// lifetime definitions. The slices have the same lifetime as this iterator.
89+
type Item = (&'static [u16], &'static [u16]);
8190

82-
fn next(&mut self) -> Option<(OsString, OsString)> {
91+
fn next(&mut self) -> Option<(&'static [u16], &'static [u16])> {
8392
loop {
8493
unsafe {
8594
if *self.cur == 0 { return None }
@@ -100,16 +109,37 @@ impl Iterator for Env {
100109
Some(p) => p,
101110
None => continue,
102111
};
103-
return Some((
104-
OsStringExt::from_wide(&s[..pos]),
105-
OsStringExt::from_wide(&s[pos+1..]),
106-
))
112+
return Some((&s[..pos], &s[pos+1..]))
107113
}
108114
}
109115
}
110116
}
111117

112-
impl Drop for Env {
118+
impl Env {
119+
fn convert((a, b): (&'static [u16], &'static [u16])) -> (OsString, OsString) {
120+
(OsStringExt::from_wide(a), OsStringExt::from_wide(b))
121+
}
122+
}
123+
124+
impl Iterator for Env {
125+
type Item = (OsString, OsString);
126+
127+
fn next(&mut self) -> Option<(OsString, OsString)> {
128+
self.inner.next().map(Self::convert)
129+
}
130+
131+
fn count(self) -> usize { self.inner.count() }
132+
133+
fn nth(&mut self, n: usize) -> Option<(OsString, OsString)> {
134+
self.inner.nth(n).map(Self::convert)
135+
}
136+
137+
fn last(self) -> Option<(OsString, OsString)> {
138+
self.inner.last().map(Self::convert)
139+
}
140+
}
141+
142+
impl Drop for EnvSlices {
113143
fn drop(&mut self) {
114144
unsafe { c::FreeEnvironmentStringsW(self.base); }
115145
}
@@ -122,7 +152,7 @@ pub fn env() -> Env {
122152
panic!("failure getting env string from OS: {}",
123153
io::Error::last_os_error());
124154
}
125-
Env { base: ch, cur: ch }
155+
Env { inner: EnvSlices { base: ch, cur: ch } }
126156
}
127157
}
128158

0 commit comments

Comments
 (0)