Adding to this mutable buffer `slice_to_repeat` repeated `repeat_count` times. # Example ## Repeat the same string bytes multiple times ``` # use arrow_buffer::buffer::MutableBuffer; let mut buffer = MutableBuffer::new(0); let bytes_to_repeat = b"ab"; buffer.repeat_slice_n_times(bytes_to_repeat, 3); assert_eq!(buffer.as_slice(), b"ababab"); ``` # Panics Panics if the repeated slice byte length
(
&mut self,
slice_to_repeat: &[T],
repeat_count: usize,
)
| 309 | /// length overflows `usize`, or if reserving the required capacity fails for the same |
| 310 | /// reasons as [`MutableBuffer::reserve`]. |
| 311 | pub fn repeat_slice_n_times<T: ArrowNativeType>( |
| 312 | &mut self, |
| 313 | slice_to_repeat: &[T], |
| 314 | repeat_count: usize, |
| 315 | ) { |
| 316 | if repeat_count == 0 || slice_to_repeat.is_empty() { |
| 317 | return; |
| 318 | } |
| 319 | |
| 320 | let bytes_to_repeat = size_of_val(slice_to_repeat); |
| 321 | let repeated_bytes = repeat_count |
| 322 | .checked_mul(bytes_to_repeat) |
| 323 | .expect("repeated slice byte length overflow"); |
| 324 | self.len |
| 325 | .checked_add(repeated_bytes) |
| 326 | .expect("mutable buffer length overflow"); |
| 327 | |
| 328 | // Ensure capacity |
| 329 | self.reserve(repeated_bytes); |
| 330 | |
| 331 | // Save the length before we do all the copies to know where to start from |
| 332 | let length_before = self.len; |
| 333 | |
| 334 | // Copy the initial slice once so we can use doubling strategy on it |
| 335 | self.extend_from_slice(slice_to_repeat); |
| 336 | |
| 337 | // This tracks how much bytes we have added by repeating so far |
| 338 | let added_repeats_length = bytes_to_repeat; |
| 339 | assert_eq!( |
| 340 | self.len - length_before, |
| 341 | added_repeats_length, |
| 342 | "should copy exactly the same number of bytes" |
| 343 | ); |
| 344 | |
| 345 | // Number of times the slice was repeated |
| 346 | let mut already_repeated_times = 1; |
| 347 | |
| 348 | // We will use doubling strategy to fill the buffer in log(repeat_count) steps |
| 349 | while already_repeated_times < repeat_count { |
| 350 | // How many slices can we copy in this iteration |
| 351 | // (either double what we have, or just the remaining ones) |
| 352 | let number_of_slices_to_copy = |
| 353 | already_repeated_times.min(repeat_count - already_repeated_times); |
| 354 | let number_of_bytes_to_copy = number_of_slices_to_copy * bytes_to_repeat; |
| 355 | |
| 356 | unsafe { |
| 357 | // Get to the start of the data before we started copying anything |
| 358 | let src = self.data.as_ptr().add(length_before) as *const u8; |
| 359 | |
| 360 | // Go to the current location to copy to (end of current data) |
| 361 | let dst = self.data.as_ptr().add(self.len); |
| 362 | |
| 363 | // SAFETY: the pointers are not overlapping as there is `number_of_bytes_to_copy` or less between them |
| 364 | std::ptr::copy_nonoverlapping(src, dst, number_of_bytes_to_copy) |
| 365 | } |
| 366 | |
| 367 | // Advance the length by the amount of data we just copied (doubled) |
| 368 | self.len += number_of_bytes_to_copy; |