(
string_array: &S,
number_array: &Int64Array,
max_item_capacity: usize,
mut builder: B,
)
| 255 | } |
| 256 | |
| 257 | fn repeat_impl<'a, S, B>( |
| 258 | string_array: &S, |
| 259 | number_array: &Int64Array, |
| 260 | max_item_capacity: usize, |
| 261 | mut builder: B, |
| 262 | ) -> Result<ArrayRef> |
| 263 | where |
| 264 | S: StringArrayType<'a> + 'a, |
| 265 | B: BulkNullStringArrayBuilder, |
| 266 | { |
| 267 | // Reusable buffer to avoid allocations in string.repeat() |
| 268 | let mut buffer = Vec::<u8>::with_capacity(max_item_capacity); |
| 269 | |
| 270 | // Helper function to repeat a string into a buffer using doubling strategy |
| 271 | // count must be > 0 |
| 272 | #[inline] |
| 273 | fn repeat_to_buffer(buffer: &mut Vec<u8>, string: &str, count: usize) { |
| 274 | buffer.clear(); |
| 275 | if !string.is_empty() { |
| 276 | let src = string.as_bytes(); |
| 277 | // Initial copy |
| 278 | buffer.extend_from_slice(src); |
| 279 | // Doubling strategy: copy what we have so far until we reach the target |
| 280 | while buffer.len() < src.len() * count { |
| 281 | let copy_len = buffer.len().min(src.len() * count - buffer.len()); |
| 282 | // SAFETY: we're copying valid UTF-8 bytes that we already verified |
| 283 | buffer.extend_from_within(..copy_len); |
| 284 | } |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | // Output is null IFF either input is null |
| 289 | let nulls = NullBuffer::union(string_array.nulls(), number_array.nulls()); |
| 290 | |
| 291 | if let Some(ref n) = nulls { |
| 292 | for i in 0..string_array.len() { |
| 293 | if n.is_null(i) { |
| 294 | builder.append_placeholder(); |
| 295 | continue; |
| 296 | } |
| 297 | // SAFETY: index `i` in both arrays is valid |
| 298 | let string = unsafe { string_array.value_unchecked(i) }; |
| 299 | let count = unsafe { number_array.value_unchecked(i) }; |
| 300 | if count > 0 { |
| 301 | repeat_to_buffer(&mut buffer, string, count as usize); |
| 302 | // SAFETY: buffer contains valid UTF-8 since we only copy from a valid &str |
| 303 | builder.append_value(unsafe { std::str::from_utf8_unchecked(&buffer) }); |
| 304 | } else { |
| 305 | builder.append_value(""); |
| 306 | } |
| 307 | } |
| 308 | } else { |
| 309 | for i in 0..string_array.len() { |
| 310 | // SAFETY: no nulls, so every index in both arrays is valid |
| 311 | let string = unsafe { string_array.value_unchecked(i) }; |
| 312 | let count = unsafe { number_array.value_unchecked(i) }; |
| 313 | if count > 0 { |
| 314 | repeat_to_buffer(&mut buffer, string, count as usize); |
no test coverage detected
searching dependent graphs…