(
array: &FixedSizeBinaryArray,
old_len: usize,
start: i64,
length: Option<u64>,
)
| 326 | } |
| 327 | |
| 328 | fn fixed_size_binary_substring( |
| 329 | array: &FixedSizeBinaryArray, |
| 330 | old_len: usize, |
| 331 | start: i64, |
| 332 | length: Option<u64>, |
| 333 | ) -> Result<ArrayRef, ArrowError> { |
| 334 | let new_start = match start.cmp(&0) { |
| 335 | Ordering::Greater => usize::try_from(start).unwrap_or(usize::MAX).min(old_len), |
| 336 | Ordering::Equal => 0, |
| 337 | Ordering::Less => { |
| 338 | let offset = usize::try_from(start.unsigned_abs()).unwrap_or(usize::MAX); |
| 339 | old_len.saturating_sub(offset) |
| 340 | } |
| 341 | }; |
| 342 | |
| 343 | let new_len = match length { |
| 344 | Some(len) => usize::try_from(len) |
| 345 | .unwrap_or(usize::MAX) |
| 346 | .min(old_len - new_start), |
| 347 | None => old_len - new_start, |
| 348 | }; |
| 349 | |
| 350 | // build value buffer |
| 351 | let num_of_elements = array.len(); |
| 352 | let data = array.value_data(); |
| 353 | let capacity = num_of_elements |
| 354 | .checked_mul(new_len) |
| 355 | .expect("capacity overflow"); |
| 356 | let mut new_values = MutableBuffer::new(capacity); |
| 357 | (0..num_of_elements) |
| 358 | .map(|idx| { |
| 359 | let offset = idx * array.value_size(); |
| 360 | (offset + new_start, offset + new_start + new_len) |
| 361 | }) |
| 362 | .for_each(|(start, end)| new_values.extend_from_slice(&data[start..end])); |
| 363 | |
| 364 | let mut nulls = array |
| 365 | .nulls() |
| 366 | .map(|n| n.inner().sliced()) |
| 367 | .and_then(|b| NullBuffer::from_unsliced_buffer(b, num_of_elements)); |
| 368 | |
| 369 | if new_len == 0 && nulls.is_none() { |
| 370 | // FixedSizeBinaryArray::new takes length from the values buffer, except when size == 0. |
| 371 | // In that case it uses the null buffer length, so preserve the original length here. |
| 372 | // Example: ["", "", ""] -> substring(..., 1, Some(2)) should keep len=3; |
| 373 | // otherwise it collapses to an empty array (len=0). |
| 374 | nulls = Some(NullBuffer::new_valid(num_of_elements)); |
| 375 | } |
| 376 | |
| 377 | let new_len: i32 = new_len.try_into().expect("new_len overflow"); |
| 378 | |
| 379 | Ok(Arc::new(FixedSizeBinaryArray::new( |
| 380 | new_len, |
| 381 | new_values.into(), |
| 382 | nulls, |
| 383 | ))) |
| 384 | } |
| 385 |
no test coverage detected