@@ -130,9 +130,9 @@ macro_rules! spezialize_for_lengths {
130130macro_rules! copy_slice_and_advance {
131131 ( $target: expr, $bytes: expr) => {
132132 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 ;
136136 }
137137}
138138
@@ -152,36 +152,42 @@ where
152152{
153153 let sep_len = sep. len ( ) ;
154154 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)
164170 } ) . expect ( "attempt to join into collection with len > usize::MAX" ) ;
165171
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) ;
168175
169- unsafe {
170- result. extend_from_slice ( first. borrow ( ) . as_ref ( ) ) ;
176+ result. extend_from_slice ( first. borrow ( ) . as_ref ( ) ) ;
171177
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) ;
175182
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 ) ;
182187 }
183- result
184- } )
188+ result. set_len ( len) ;
189+ }
190+ result
185191}
186192
187193#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments