@@ -131,9 +131,9 @@ macro_rules! spezialize_for_lengths {
131
131
macro_rules! copy_slice_and_advance {
132
132
( $target: expr, $bytes: expr) => {
133
133
let len = $bytes. len( ) ;
134
- $target. get_unchecked_mut ( .. len)
135
- . copy_from_slice( $bytes) ;
136
- $target = { $target } . get_unchecked_mut ( len.. ) ;
134
+ let ( head , tail ) = { $target} . split_at_mut ( len) ;
135
+ head . copy_from_slice( $bytes) ;
136
+ $target = tail ;
137
137
}
138
138
}
139
139
@@ -153,36 +153,42 @@ where
153
153
{
154
154
let sep_len = sep. len ( ) ;
155
155
let mut iter = slice. iter ( ) ;
156
- iter. next ( ) . map_or ( vec ! [ ] , |first| {
157
- // this is wrong without the guarantee that `slice` is non-empty
158
- // if the `len` calculation overflows, we'll panic
159
- // we would have run out of memory anyway and the rest of the function requires
160
- // the entire String pre-allocated for safety
161
- //
162
- // this is the exact len of the resulting String
163
- let len = sep_len. checked_mul ( slice. len ( ) - 1 ) . and_then ( |n| {
164
- slice. iter ( ) . map ( |s| s. borrow ( ) . as_ref ( ) . len ( ) ) . try_fold ( n, usize:: checked_add)
156
+
157
+ // the first slice is the only one without a separator preceding it
158
+ let first = match iter. next ( ) {
159
+ Some ( first) => first,
160
+ None => return vec ! [ ] ,
161
+ } ;
162
+
163
+ // compute the exact total length of the joined Vec
164
+ // if the `len` calculation overflows, we'll panic
165
+ // we would have run out of memory anyway and the rest of the function requires
166
+ // the entire Vec pre-allocated for safety
167
+ let len = sep_len. checked_mul ( iter. len ( ) ) . and_then ( |n| {
168
+ slice. iter ( )
169
+ . map ( |s| s. borrow ( ) . as_ref ( ) . len ( ) )
170
+ . try_fold ( n, usize:: checked_add)
165
171
} ) . expect ( "attempt to join into collection with len > usize::MAX" ) ;
166
172
167
- // crucial for safety
168
- let mut result = Vec :: with_capacity ( len) ;
173
+ // crucial for safety
174
+ let mut result = Vec :: with_capacity ( len) ;
175
+ assert ! ( result. capacity( ) >= len) ;
169
176
170
- unsafe {
171
- result. extend_from_slice ( first. borrow ( ) . as_ref ( ) ) ;
177
+ result. extend_from_slice ( first. borrow ( ) . as_ref ( ) ) ;
172
178
173
- {
174
- let pos = result. len ( ) ;
175
- let target = result. get_unchecked_mut ( pos..len) ;
179
+ unsafe {
180
+ {
181
+ let pos = result. len ( ) ;
182
+ let target = result. get_unchecked_mut ( pos..len) ;
176
183
177
- // copy separator and strs over without bounds checks
178
- // generate loops with hardcoded offsets for small separators
179
- // massive improvements possible (~ x2)
180
- spezialize_for_lengths ! ( sep, target, iter; 0 , 1 , 2 , 3 , 4 ) ;
181
- }
182
- result. set_len ( len) ;
184
+ // copy separator and slices over without bounds checks
185
+ // generate loops with hardcoded offsets for small separators
186
+ // massive improvements possible (~ x2)
187
+ spezialize_for_lengths ! ( sep, target, iter; 0 , 1 , 2 , 3 , 4 ) ;
183
188
}
184
- result
185
- } )
189
+ result. set_len ( len) ;
190
+ }
191
+ result
186
192
}
187
193
188
194
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments