Pushes an [`Array`] that is built from a closure. __WARNING__: This is fairly "sharp" tool that is easy to get wrong. You should prefer [`RowPacker::try_push_array`] when possible. Returns an error if the number of elements pushed does not match the cardinality of the array as described by `dims`, or if the number of dimensions exceeds [`MAX_ARRAY_DIMENSIONS`]. If an error occurs, the packer's s
(
&mut self,
dims: I,
f: F,
)
| 2601 | /// number of dimensions exceeds [`MAX_ARRAY_DIMENSIONS`]. If an error |
| 2602 | /// occurs, the packer's state will be unchanged. |
| 2603 | pub fn push_array_with_row_major<F, I>( |
| 2604 | &mut self, |
| 2605 | dims: I, |
| 2606 | f: F, |
| 2607 | ) -> Result<(), InvalidArrayError> |
| 2608 | where |
| 2609 | I: IntoIterator<Item = ArrayDimension>, |
| 2610 | F: FnOnce(&mut RowPacker) -> usize, |
| 2611 | { |
| 2612 | let start = self.row.data.len(); |
| 2613 | self.row.data.push(Tag::Array.into()); |
| 2614 | |
| 2615 | // Write dummy dimension length for now, we'll fix it up. |
| 2616 | let dims_start = self.row.data.len(); |
| 2617 | self.row.data.push(42); |
| 2618 | |
| 2619 | let mut num_dims: u8 = 0; |
| 2620 | let mut cardinality: usize = 1; |
| 2621 | for dim in dims { |
| 2622 | num_dims += 1; |
| 2623 | // Saturate: an overflowing cardinality is impossibly large and is |
| 2624 | // rejected by the `nelements` check below. See the matching note in |
| 2625 | // `push_array_with_unchecked`. |
| 2626 | cardinality = cardinality.saturating_mul(dim.length); |
| 2627 | |
| 2628 | self.row |
| 2629 | .data |
| 2630 | .extend_from_slice(&i64::cast_from(dim.lower_bound).to_le_bytes()); |
| 2631 | self.row |
| 2632 | .data |
| 2633 | .extend_from_slice(&u64::cast_from(dim.length).to_le_bytes()); |
| 2634 | } |
| 2635 | |
| 2636 | if num_dims > MAX_ARRAY_DIMENSIONS { |
| 2637 | // Reset the packer state so we don't have invalid data. |
| 2638 | self.row.data.truncate(start); |
| 2639 | return Err(InvalidArrayError::TooManyDimensions(usize::from(num_dims))); |
| 2640 | } |
| 2641 | // Fix up our dimension length. |
| 2642 | self.row.data[dims_start..dims_start + size_of::<u8>()] |
| 2643 | .copy_from_slice(&num_dims.to_le_bytes()); |
| 2644 | |
| 2645 | // Write elements. |
| 2646 | let off = self.row.data.len(); |
| 2647 | self.row.data.extend_from_slice(&[0; size_of::<u64>()]); |
| 2648 | |
| 2649 | let nelements = f(self); |
| 2650 | |
| 2651 | let len = u64::cast_from(self.row.data.len() - off - size_of::<u64>()); |
| 2652 | self.row.data[off..off + size_of::<u64>()].copy_from_slice(&len.to_le_bytes()); |
| 2653 | |
| 2654 | // Check that the number of elements written matches the dimension |
| 2655 | // information. |
| 2656 | let cardinality = match num_dims { |
| 2657 | 0 => 0, |
| 2658 | _ => cardinality, |
| 2659 | }; |
| 2660 | if nelements != cardinality { |
no test coverage detected