| 884 | /// Overload for GetSpaced for a single run in a RleDecoder |
| 885 | template <typename Converter, typename BitRunReader, typename BitRun, typename value_type> |
| 886 | auto RunGetSpaced(Converter* converter, typename Converter::out_type* out, |
| 887 | rle_size_t batch_size, rle_size_t null_count, |
| 888 | rle_size_t value_bit_width, BitRunReader* validity_reader, |
| 889 | BitRun* validity_run, |
| 890 | RleRunDecoder<value_type>* decoder) -> GetSpacedResult<rle_size_t> { |
| 891 | ARROW_DCHECK_GT(batch_size, 0); |
| 892 | // The equality case is handled in the main loop in GetSpaced |
| 893 | ARROW_DCHECK_LT(null_count, batch_size); |
| 894 | |
| 895 | auto batch = BatchCounter::FromBatchSizeAndNulls(batch_size, null_count); |
| 896 | |
| 897 | const rle_size_t values_available = decoder->remaining(); |
| 898 | ARROW_DCHECK_GT(values_available, 0); |
| 899 | auto values_remaining_run = [&]() { |
| 900 | auto out = values_available - batch.values_read(); |
| 901 | ARROW_DCHECK_GE(out, 0); |
| 902 | return out; |
| 903 | }; |
| 904 | |
| 905 | // Consume as much as possible from the repeated run. |
| 906 | // We only need to count the number of nulls and non-nulls because we can fill in the |
| 907 | // same value for nulls and non-nulls. |
| 908 | // This proves to be a big efficiency win. |
| 909 | while (values_remaining_run() > 0 && !batch.is_done()) { |
| 910 | ARROW_DCHECK_GE(validity_run->length, 0); |
| 911 | ARROW_DCHECK_LT(validity_run->length, max_size_for_v<rle_size_t>); |
| 912 | ARROW_DCHECK_LE(validity_run->length, batch.total_remaining()); |
| 913 | const auto& validity_run_size = static_cast<rle_size_t>(validity_run->length); |
| 914 | |
| 915 | if (validity_run->set) { |
| 916 | // We may end the current RLE run in the middle of the validity run |
| 917 | auto update_size = std::min(validity_run_size, values_remaining_run()); |
| 918 | batch.AccrueReadValues(update_size); |
| 919 | validity_run->length -= update_size; |
| 920 | } else { |
| 921 | // We can consume all nulls here because it does not matter if we consume on this |
| 922 | // RLE run, or an a next encoded run. The value filled does not matter. |
| 923 | auto update_size = std::min(validity_run_size, batch.null_remaining()); |
| 924 | batch.AccrueReadNulls(update_size); |
| 925 | validity_run->length -= update_size; |
| 926 | } |
| 927 | |
| 928 | if (ARROW_PREDICT_TRUE(validity_run->length == 0)) { |
| 929 | *validity_run = validity_reader->NextRun(); |
| 930 | } |
| 931 | } |
| 932 | |
| 933 | const value_type value = decoder->value(); |
| 934 | if (ARROW_PREDICT_FALSE(!converter->InputIsValid(value))) { |
| 935 | return {0, 0}; |
| 936 | } |
| 937 | converter->WriteRepeated(out, out + batch.total_read(), value); |
| 938 | const auto actual_values_read = decoder->Advance(batch.values_read()); |
| 939 | // We always cropped the number of values_read by the remaining values in the run. |
| 940 | // What's more the RLE decoder should not encounter any errors. |
| 941 | ARROW_DCHECK_EQ(actual_values_read, batch.values_read()); |
| 942 | |
| 943 | return {/* .values_read= */ batch.values_read(), /* .null_read= */ batch.null_read()}; |
no test coverage detected