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