@@ -72,14 +72,23 @@ pub fn error_string(errnum: i32) -> String {
72
72
}
73
73
74
74
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 {
75
82
base : c:: LPWCH ,
76
83
cur : c:: LPWCH ,
77
84
}
78
85
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 ] ) ;
81
90
82
- fn next ( & mut self ) -> Option < ( OsString , OsString ) > {
91
+ fn next ( & mut self ) -> Option < ( & ' static [ u16 ] , & ' static [ u16 ] ) > {
83
92
loop {
84
93
unsafe {
85
94
if * self . cur == 0 { return None }
@@ -100,16 +109,37 @@ impl Iterator for Env {
100
109
Some ( p) => p,
101
110
None => continue ,
102
111
} ;
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 ..] ) )
107
113
}
108
114
}
109
115
}
110
116
}
111
117
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 {
113
143
fn drop ( & mut self ) {
114
144
unsafe { c:: FreeEnvironmentStringsW ( self . base ) ; }
115
145
}
@@ -122,7 +152,7 @@ pub fn env() -> Env {
122
152
panic ! ( "failure getting env string from OS: {}" ,
123
153
io:: Error :: last_os_error( ) ) ;
124
154
}
125
- Env { base : ch, cur : ch }
155
+ Env { inner : EnvSlices { base : ch, cur : ch } }
126
156
}
127
157
}
128
158
0 commit comments