The take kernel implementation for `FixedSizeBinaryArray`. The computation is done in two steps: - Compute the values buffer - Compute the null buffer
(
values: &FixedSizeBinaryArray,
indices: &PrimitiveArray<IndexType>,
size: i32,
)
| 796 | /// - Compute the values buffer |
| 797 | /// - Compute the null buffer |
| 798 | fn take_fixed_size_binary<IndexType: ArrowPrimitiveType>( |
| 799 | values: &FixedSizeBinaryArray, |
| 800 | indices: &PrimitiveArray<IndexType>, |
| 801 | size: i32, |
| 802 | ) -> Result<FixedSizeBinaryArray, ArrowError> { |
| 803 | let size_usize = usize::try_from(size).map_err(|_| { |
| 804 | ArrowError::InvalidArgumentError(format!("Cannot convert size '{}' to usize", size)) |
| 805 | })?; |
| 806 | |
| 807 | let result_buffer = match size_usize { |
| 808 | 1 => take_fixed_size::<IndexType, 1>(values.values(), indices), |
| 809 | 2 => take_fixed_size::<IndexType, 2>(values.values(), indices), |
| 810 | 4 => take_fixed_size::<IndexType, 4>(values.values(), indices), |
| 811 | 8 => take_fixed_size::<IndexType, 8>(values.values(), indices), |
| 812 | 16 => take_fixed_size::<IndexType, 16>(values.values(), indices), |
| 813 | _ => take_fixed_size_binary_buffer_dynamic_length(values, indices, size_usize), |
| 814 | }; |
| 815 | |
| 816 | let value_nulls = take_nulls(values.nulls(), indices); |
| 817 | let final_nulls = NullBuffer::union(value_nulls.as_ref(), indices.nulls()); |
| 818 | let array_data = ArrayDataBuilder::new(DataType::FixedSizeBinary(size)) |
| 819 | .len(indices.len()) |
| 820 | .nulls(final_nulls) |
| 821 | .offset(0) |
| 822 | .add_buffer(result_buffer) |
| 823 | .build()?; |
| 824 | |
| 825 | return Ok(FixedSizeBinaryArray::from(array_data)); |
| 826 | |
| 827 | /// Implementation of the take kernel for fixed size binary arrays. |
| 828 | #[inline(never)] |
| 829 | fn take_fixed_size_binary_buffer_dynamic_length<IndexType: ArrowPrimitiveType>( |
| 830 | values: &FixedSizeBinaryArray, |
| 831 | indices: &PrimitiveArray<IndexType>, |
| 832 | size_usize: usize, |
| 833 | ) -> Buffer { |
| 834 | let values_buffer = values.values().as_slice(); |
| 835 | let mut values_buffer_builder = BufferBuilder::new(indices.len() * size_usize); |
| 836 | |
| 837 | if indices.null_count() == 0 { |
| 838 | let array_iter = indices.values().iter().map(|idx| { |
| 839 | let offset = idx.as_usize() * size_usize; |
| 840 | &values_buffer[offset..offset + size_usize] |
| 841 | }); |
| 842 | for slice in array_iter { |
| 843 | values_buffer_builder.append_slice(slice); |
| 844 | } |
| 845 | } else { |
| 846 | // The indices nullability cannot be ignored here because the values buffer may contain |
| 847 | // nulls which should not cause a panic. |
| 848 | let array_iter = indices.iter().map(|idx| { |
| 849 | idx.map(|idx| { |
| 850 | let offset = idx.as_usize() * size_usize; |
| 851 | &values_buffer[offset..offset + size_usize] |
| 852 | }) |
| 853 | }); |
| 854 | for slice in array_iter { |
| 855 | match slice { |