Skip to main content

parquet/column/reader/
decoder.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use bytes::Bytes;
19
20use crate::basic::{Encoding, EncodingMask, Type};
21use crate::data_type::DataType;
22use crate::encodings::{
23    decoding::{Decoder, DictDecoder, PlainDecoder, get_decoder},
24    rle::RleDecoder,
25};
26use crate::errors::{ParquetError, Result};
27use crate::schema::types::ColumnDescPtr;
28use crate::util::bit_util::{BitReader, num_required_bits};
29
30/// Decodes level data
31pub trait ColumnLevelDecoder {
32    type Buffer;
33
34    /// Set data for this [`ColumnLevelDecoder`]
35    fn set_data(&mut self, encoding: Encoding, data: Bytes) -> Result<()>;
36}
37
38pub trait RepetitionLevelDecoder: ColumnLevelDecoder {
39    /// Reads up to `num_records` records, and at most `num_levels` levels, of repetition
40    /// level data into `out`, returning the number of complete records and levels read.
41    ///
42    /// A record only ends when the data contains a subsequent repetition level of 0;
43    /// it is therefore left to the caller to delimit the final record in a column.
44    fn read_rep_levels(
45        &mut self,
46        out: &mut Self::Buffer,
47        num_records: usize,
48        num_levels: usize,
49    ) -> Result<(usize, usize)>;
50
51    /// Skips over up to `num_levels` repetition levels corresponding to `num_records`
52    /// records, where a record is delimited by a repetition level of 0.
53    ///
54    /// Returns the number of records skipped, and the number of levels skipped.
55    ///
56    /// A record only ends when the data contains a subsequent repetition level of 0;
57    /// it is therefore left to the caller to delimit the final record in a column.
58    fn skip_rep_levels(&mut self, num_records: usize, num_levels: usize) -> Result<(usize, usize)>;
59
60    /// Flush any partially read or skipped record.
61    ///
62    /// Returns true if there was such a record, which the caller should count
63    /// as complete.
64    fn flush_partial(&mut self) -> bool;
65}
66
67pub trait DefinitionLevelDecoder: ColumnLevelDecoder {
68    /// Read up to `num_levels` definition levels into `out`.
69    ///
70    /// Returns the number of values read, and the number of levels read.
71    fn read_def_levels(
72        &mut self,
73        out: &mut Self::Buffer,
74        num_levels: usize,
75    ) -> Result<(usize, usize)>;
76
77    /// Skips over `num_levels` definition levels.
78    ///
79    /// Returns the number of values skipped, and the number of levels skipped.
80    fn skip_def_levels(&mut self, num_levels: usize) -> Result<(usize, usize)>;
81}
82
83/// Decodes value data
84pub trait ColumnValueDecoder {
85    type Buffer;
86
87    /// Create a new [`ColumnValueDecoder`]
88    fn new(col: &ColumnDescPtr) -> Self;
89
90    /// Set the current dictionary page
91    fn set_dict(
92        &mut self,
93        buf: Bytes,
94        num_values: u32,
95        encoding: Encoding,
96        is_sorted: bool,
97    ) -> Result<()>;
98
99    /// Set the current data page
100    ///
101    /// - `encoding` - the encoding of the page
102    /// - `data` - a point to the page's uncompressed value data
103    /// - `num_levels` - the number of levels contained within the page, i.e. values including nulls
104    /// - `num_values` - the number of non-null values contained within the page (V2 page only)
105    ///
106    /// Note: data encoded with [`Encoding::RLE`] may not know its exact length, as the final
107    /// run may be zero-padded. As such if `num_values` is not provided (i.e. `None`),
108    /// subsequent calls to `ColumnValueDecoder::read` may yield more values than
109    /// non-null definition levels within the page
110    fn set_data(
111        &mut self,
112        encoding: Encoding,
113        data: Bytes,
114        num_levels: usize,
115        num_values: Option<usize>,
116    ) -> Result<()>;
117
118    /// Read up to `num_values` values into `out`.
119    fn read(&mut self, out: &mut Self::Buffer, num_values: usize) -> Result<usize>;
120
121    /// Skips over `num_values` values
122    ///
123    /// Returns the number of values skipped
124    fn skip_values(&mut self, num_values: usize) -> Result<usize>;
125}
126
127fn fixed_len_byte_array_payload_size(
128    num_values: usize,
129    type_length: usize,
130    page: &str,
131) -> Result<usize> {
132    num_values.checked_mul(type_length).ok_or_else(|| {
133        general_err!(
134            "FIXED_LEN_BYTE_ARRAY {} payload size overflow: {} values of {} bytes",
135            page,
136            num_values,
137            type_length
138        )
139    })
140}
141
142/// Validate a complete decompressed PLAIN FLBA value section, excluding levels.
143/// `num_values` must count physical non-null values, not rows or requested values.
144/// Canonical payloads are returned unchanged, even if values resemble prefixes.
145pub(crate) fn normalize_fixed_len_byte_array_payload(
146    data: Bytes,
147    num_values: usize,
148    type_length: usize,
149    page: &str,
150) -> Result<Bytes> {
151    let expected_len = fixed_len_byte_array_payload_size(num_values, type_length, page)?;
152    if data.len() == expected_len {
153        return Ok(data);
154    }
155
156    // Temporary mitigation for arrow-rs #11261, reached only for a noncanonical
157    // size. Keep the repair separate from ordinary validation and value decoding.
158    super::legacy_fixed_len_byte_array::decode_length_prefixed_plain(
159        data,
160        num_values,
161        type_length,
162        expected_len,
163        page,
164    )
165}
166
167/// Prepare a complete FLBA data-page value section after extracting the levels.
168/// PLAIN requires exact size validation; other compliant encodings are unchanged.
169pub(crate) fn normalize_fixed_len_byte_array_data(
170    data: Bytes,
171    num_values: usize,
172    type_length: usize,
173    encoding: Encoding,
174) -> Result<(Encoding, Bytes)> {
175    match encoding {
176        Encoding::PLAIN => Ok((
177            encoding,
178            normalize_fixed_len_byte_array_payload(
179                data,
180                num_values,
181                type_length,
182                "PLAIN data page",
183            )?,
184        )),
185        Encoding::DELTA_LENGTH_BYTE_ARRAY => {
186            // Temporary mitigation only: this encoding is not defined for FLBA.
187            // Do not add support for it to the ordinary value decoders.
188            let expected_len = fixed_len_byte_array_payload_size(
189                num_values,
190                type_length,
191                "DELTA_LENGTH_BYTE_ARRAY data page",
192            )?;
193            let data = super::legacy_fixed_len_byte_array::decode_delta_length(
194                data,
195                num_values,
196                type_length,
197                expected_len,
198            )?;
199            Ok((Encoding::PLAIN, data))
200        }
201        _ => Ok((encoding, data)),
202    }
203}
204
205/// A value section ready for its ordinary decoder. When `validate_count` is set,
206/// account for its physical values during normal level decoding.
207pub(super) struct PreparedFixedLenByteArrayPage {
208    pub(super) encoding: Encoding,
209    pub(super) data: Bytes,
210    pub(super) validate_count: bool,
211}
212
213/// Prepare V1 FLBA values without teaching the column reader historical layouts.
214/// `definition_levels` contains the maximum level, encoding and encoded levels;
215/// absent levels mean that the page's physical count is already known.
216pub(super) fn prepare_v1_fixed_len_byte_array(
217    data: Bytes,
218    num_levels: usize,
219    type_length: usize,
220    encoding: Encoding,
221    definition_levels: Option<(i16, Encoding, &Bytes)>,
222) -> Result<PreparedFixedLenByteArrayPage> {
223    let Some((max_level, level_encoding, levels)) = definition_levels else {
224        let (encoding, data) =
225            normalize_fixed_len_byte_array_data(data, num_levels, type_length, encoding)?;
226        return Ok(PreparedFixedLenByteArrayPage {
227            encoding,
228            data,
229            validate_count: false,
230        });
231    };
232
233    // This callback is lazy: ordinary nullable pages do not create a second
234    // decoder or traverse their levels before normal reading begins.
235    let count_values = || {
236        let mut counter = DefinitionLevelDecoderImpl::new(max_level);
237        counter.set_data(level_encoding, levels.clone())?;
238        let (values, read) = counter.skip_def_levels(num_levels)?;
239        if read != num_levels {
240            return Err(general_err!(
241                "Invalid FIXED_LEN_BYTE_ARRAY {encoding} data page: \
242                 expected {num_levels} definition levels, got {read}"
243            ));
244        }
245        Ok(values)
246    };
247
248    let mut page = PreparedFixedLenByteArrayPage {
249        encoding,
250        data,
251        validate_count: false,
252    };
253    // Temporary compatibility hook. Removing it leaves the canonical path and
254    // its physical-value validation intact.
255    if super::legacy_fixed_len_byte_array::prepare_v1_page(
256        &mut page,
257        num_levels,
258        type_length,
259        &count_values,
260    )? {
261        return Ok(page);
262    }
263
264    if encoding == Encoding::PLAIN {
265        if num_levels == 0 || type_length == 0 {
266            // Preserve empty-page header validation and avoid a zero-width
267            // byte budget, which cannot establish the physical value count.
268            page.data = normalize_fixed_len_byte_array_payload(
269                page.data,
270                count_values()?,
271                type_length,
272                "PLAIN data page",
273            )?;
274        } else {
275            if !page.data.len().is_multiple_of(type_length) {
276                return Err(general_err!(
277                    "Invalid FIXED_LEN_BYTE_ARRAY PLAIN data page payload length: \
278                     {} bytes is not a multiple of {type_length}",
279                    page.data.len()
280                ));
281            }
282            page.validate_count = true;
283        }
284    }
285    Ok(page)
286}
287
288/// Bucket-based storage for decoder instances keyed by `Encoding`.
289///
290/// This replaces `HashMap` lookups with direct indexing to avoid hashing overhead in the
291/// hot decoding paths.
292const ENCODING_SLOTS: usize = Encoding::MAX_DISCRIMINANT as usize + 1;
293
294/// An implementation of [`ColumnValueDecoder`] for `[T::T]`
295pub struct ColumnValueDecoderImpl<T: DataType> {
296    descr: ColumnDescPtr,
297
298    current_encoding: Option<Encoding>,
299
300    /// Cache of decoders for existing encodings.
301    /// Uses `EncodingMask` and dense storage keyed by encoding discriminant.
302    decoder_mask: EncodingMask,
303    decoders: [Option<Box<dyn Decoder<T>>>; ENCODING_SLOTS],
304}
305
306impl<T: DataType> ColumnValueDecoder for ColumnValueDecoderImpl<T> {
307    type Buffer = Vec<T::T>;
308
309    fn new(descr: &ColumnDescPtr) -> Self {
310        Self {
311            descr: descr.clone(),
312            current_encoding: None,
313            decoder_mask: EncodingMask::default(),
314            decoders: std::array::from_fn(|_| None),
315        }
316    }
317
318    fn set_dict(
319        &mut self,
320        buf: Bytes,
321        num_values: u32,
322        mut encoding: Encoding,
323        _is_sorted: bool,
324    ) -> Result<()> {
325        if encoding == Encoding::PLAIN || encoding == Encoding::PLAIN_DICTIONARY {
326            encoding = Encoding::RLE_DICTIONARY
327        }
328
329        if self.decoder_mask.is_set(encoding) {
330            return Err(general_err!("Column cannot have more than one dictionary"));
331        }
332
333        if encoding == Encoding::RLE_DICTIONARY {
334            let buf = if self.descr.physical_type() == Type::FIXED_LEN_BYTE_ARRAY {
335                normalize_fixed_len_byte_array_payload(
336                    buf,
337                    num_values as usize,
338                    self.descr.type_length() as usize,
339                    "dictionary page",
340                )?
341            } else {
342                buf
343            };
344            let mut dictionary = PlainDecoder::<T>::new(self.descr.type_length());
345            dictionary.set_data(buf, num_values as usize)?;
346
347            let mut decoder = DictDecoder::new();
348            decoder.set_dict(Box::new(dictionary))?;
349            self.decoders[encoding as usize] = Some(Box::new(decoder));
350            self.decoder_mask.insert(encoding);
351            Ok(())
352        } else {
353            Err(nyi_err!(
354                "Invalid/Unsupported encoding type for dictionary: {}",
355                encoding
356            ))
357        }
358    }
359
360    fn set_data(
361        &mut self,
362        mut encoding: Encoding,
363        data: Bytes,
364        num_levels: usize,
365        num_values: Option<usize>,
366    ) -> Result<()> {
367        if encoding == Encoding::PLAIN_DICTIONARY {
368            encoding = Encoding::RLE_DICTIONARY;
369        }
370
371        let decoder = if encoding == Encoding::RLE_DICTIONARY {
372            self.decoders[encoding as usize]
373                .as_mut()
374                .expect("Decoder for dict should have been set")
375        } else {
376            let slot = encoding as usize;
377            if self.decoders[slot].is_none() {
378                let data_decoder = get_decoder::<T>(self.descr.clone(), encoding)?;
379                self.decoders[slot] = Some(data_decoder);
380                self.decoder_mask.insert(encoding);
381            }
382            self.decoders[slot]
383                .as_mut()
384                .expect("decoder should have been inserted")
385        };
386
387        decoder.set_data(data, num_values.unwrap_or(num_levels))?;
388        self.current_encoding = Some(encoding);
389        Ok(())
390    }
391
392    fn read(&mut self, out: &mut Self::Buffer, num_values: usize) -> Result<usize> {
393        let encoding = self
394            .current_encoding
395            .expect("current_encoding should be set");
396
397        let current_decoder = self.decoders[encoding as usize]
398            .as_mut()
399            .unwrap_or_else(|| panic!("decoder for encoding {encoding} should be set"));
400
401        // TODO: Push vec into decoder (#5177)
402        let start = out.len();
403        out.resize(start + num_values, T::T::default());
404        let read = current_decoder.get(&mut out[start..])?;
405        out.truncate(start + read);
406        Ok(read)
407    }
408
409    fn skip_values(&mut self, num_values: usize) -> Result<usize> {
410        let encoding = self
411            .current_encoding
412            .expect("current_encoding should be set");
413
414        let current_decoder = self.decoders[encoding as usize]
415            .as_mut()
416            .unwrap_or_else(|| panic!("decoder for encoding {encoding} should be set"));
417
418        current_decoder.skip(num_values)
419    }
420}
421
422enum LevelDecoder {
423    Packed(BitReader, u8),
424    Rle(RleDecoder),
425}
426
427impl LevelDecoder {
428    fn new(encoding: Encoding, data: Bytes, bit_width: u8) -> Result<Self> {
429        match encoding {
430            Encoding::RLE => {
431                let mut decoder = RleDecoder::new(bit_width);
432                decoder.set_data(data)?;
433                Ok(Self::Rle(decoder))
434            }
435            #[expect(deprecated)]
436            Encoding::BIT_PACKED => Ok(Self::Packed(BitReader::new(data), bit_width)),
437            _ => unreachable!("invalid level encoding: {}", encoding),
438        }
439    }
440
441    fn read(&mut self, out: &mut [i16]) -> Result<usize> {
442        match self {
443            Self::Packed(reader, bit_width) => {
444                Ok(reader.get_batch::<i16>(out, *bit_width as usize))
445            }
446            Self::Rle(reader) => Ok(reader.get_batch(out)?),
447        }
448    }
449}
450
451/// An implementation of [`DefinitionLevelDecoder`] for `[i16]`
452pub struct DefinitionLevelDecoderImpl {
453    decoder: Option<LevelDecoder>,
454    bit_width: u8,
455    max_level: i16,
456}
457
458impl DefinitionLevelDecoderImpl {
459    pub fn new(max_level: i16) -> Self {
460        let bit_width = num_required_bits(max_level as u64);
461        Self {
462            decoder: None,
463            bit_width,
464            max_level,
465        }
466    }
467}
468
469impl ColumnLevelDecoder for DefinitionLevelDecoderImpl {
470    type Buffer = Vec<i16>;
471
472    fn set_data(&mut self, encoding: Encoding, data: Bytes) -> Result<()> {
473        self.decoder = Some(LevelDecoder::new(encoding, data, self.bit_width)?);
474        Ok(())
475    }
476}
477
478impl DefinitionLevelDecoder for DefinitionLevelDecoderImpl {
479    fn read_def_levels(
480        &mut self,
481        out: &mut Self::Buffer,
482        num_levels: usize,
483    ) -> Result<(usize, usize)> {
484        // TODO: Push vec into decoder (#5177)
485        let start = out.len();
486        out.resize(start + num_levels, 0);
487        let levels_read = self.decoder.as_mut().unwrap().read(&mut out[start..])?;
488        out.truncate(start + levels_read);
489
490        let values_read = count_levels_eq(&out[start..], self.max_level);
491        Ok((values_read, levels_read))
492    }
493
494    fn skip_def_levels(&mut self, num_levels: usize) -> Result<(usize, usize)> {
495        if num_levels == 0 {
496            return Ok((0, 0));
497        }
498        match self.decoder.as_mut().unwrap() {
499            LevelDecoder::Rle(reader) => reader.skip_and_count(num_levels, self.max_level),
500            LevelDecoder::Packed(reader, 1) => Ok(reader.skip_and_count_ones(num_levels)),
501            LevelDecoder::Packed(reader, bit_width) => {
502                Ok(reader.skip_and_count(num_levels, *bit_width as usize, self.max_level))
503            }
504        }
505    }
506}
507
508/// Returns the number of levels equal to `level`.
509///
510/// Summing into a `u16`, over chunks short enough that the sum cannot
511/// overflow, helps the compiler vectorize the count better than summing into
512/// a `usize`.
513fn count_levels_eq(levels: &[i16], level: i16) -> usize {
514    levels
515        .chunks(u16::MAX as usize)
516        .map(|chunk| chunk.iter().map(|&l| u16::from(l == level)).sum::<u16>() as usize)
517        .sum()
518}
519
520pub(crate) const REPETITION_LEVELS_BATCH_SIZE: usize = 1024;
521
522/// An implementation of [`RepetitionLevelDecoder`] for `[i16]`
523pub struct RepetitionLevelDecoderImpl {
524    decoder: Option<LevelDecoder>,
525    bit_width: u8,
526    buffer: Box<[i16; REPETITION_LEVELS_BATCH_SIZE]>,
527    buffer_len: usize,
528    buffer_offset: usize,
529    /// Whether the levels read so far end with a record that has not ended yet
530    has_partial: bool,
531}
532
533impl RepetitionLevelDecoderImpl {
534    pub fn new(max_level: i16) -> Self {
535        let bit_width = num_required_bits(max_level as u64);
536        Self {
537            decoder: None,
538            bit_width,
539            buffer: Box::new([0; REPETITION_LEVELS_BATCH_SIZE]),
540            buffer_offset: 0,
541            buffer_len: 0,
542            has_partial: false,
543        }
544    }
545
546    fn fill_buf(&mut self) -> Result<()> {
547        let read = self.decoder.as_mut().unwrap().read(self.buffer.as_mut())?;
548        self.buffer_offset = 0;
549        self.buffer_len = read;
550        Ok(())
551    }
552
553    /// Counts the records that end within the unread levels in `self.buffer`,
554    /// looking at no more than `num_levels` of them and stopping once
555    /// `records_to_read` records have ended.
556    ///
557    /// Each repetition level of 0 starts a new record, which ends the record
558    /// before it. If `self.has_partial` is set, the levels before the first 0
559    /// continue a record started by an earlier call.
560    ///
561    /// Returns `(partial, records_read, levels_read)`:
562    /// - If it finds the end of the last requested record
563    ///   (`records_read == records_to_read`), `partial` is false and
564    ///   `levels_read` is the number of levels in the requested records, so the
565    ///   0 that starts the next record is left unread.
566    /// - Otherwise `partial` is true and `levels_read` is the number of levels
567    ///   inspected. The last record in those levels has not ended yet, and is
568    ///   not counted in `records_read`.
569    fn count_records(&self, records_to_read: usize, num_levels: usize) -> (bool, usize, usize) {
570        let levels = num_levels.min(self.buffer_len - self.buffer_offset);
571        let buf = &self.buffer[self.buffer_offset..self.buffer_offset + levels];
572
573        // Unless a previous call left a record partially read, the first level
574        // starts a record rather than completing one, so skip it
575        let mut scan_start = usize::from(!self.has_partial && !buf.is_empty());
576
577        // Skip over chunks that complete fewer records than are still needed,
578        // counting the 0s in each chunk rather than checking each level. Chunks
579        // are kept small so that a short read does not count many levels past
580        // where it ends, but not so small that the per-chunk overhead slows
581        // down long reads.
582        const CHUNK_SIZE: usize = 32;
583        let mut records_read = 0;
584        for chunk in buf[scan_start..].chunks(CHUNK_SIZE) {
585            let complete = count_levels_eq(chunk, 0);
586            if records_read + complete >= records_to_read {
587                break;
588            }
589            records_read += complete;
590            scan_start += chunk.len();
591        }
592
593        // Find where the last requested record ends, if it ends in `buf`
594        for (idx, item) in buf.iter().enumerate().skip(scan_start) {
595            if *item == 0 {
596                records_read += 1;
597
598                if records_read == records_to_read {
599                    return (false, records_read, idx);
600                }
601            }
602        }
603        // Either ran out of space in `num_levels` or data in `self.buffer`
604        (true, records_read, levels)
605    }
606}
607
608impl ColumnLevelDecoder for RepetitionLevelDecoderImpl {
609    type Buffer = Vec<i16>;
610
611    fn set_data(&mut self, encoding: Encoding, data: Bytes) -> Result<()> {
612        self.decoder = Some(LevelDecoder::new(encoding, data, self.bit_width)?);
613        self.buffer_len = 0;
614        self.buffer_offset = 0;
615        Ok(())
616    }
617}
618
619impl RepetitionLevelDecoder for RepetitionLevelDecoderImpl {
620    fn read_rep_levels(
621        &mut self,
622        out: &mut Self::Buffer,
623        num_records: usize,
624        num_levels: usize,
625    ) -> Result<(usize, usize)> {
626        let mut total_records_read = 0;
627        let mut total_levels_read = 0;
628
629        while total_records_read < num_records && total_levels_read < num_levels {
630            if self.buffer_len == self.buffer_offset {
631                self.fill_buf()?;
632                if self.buffer_len == 0 {
633                    break;
634                }
635            }
636
637            let (partial, records_read, levels_read) = self.count_records(
638                num_records - total_records_read,
639                num_levels - total_levels_read,
640            );
641
642            out.extend_from_slice(
643                &self.buffer[self.buffer_offset..self.buffer_offset + levels_read],
644            );
645
646            total_levels_read += levels_read;
647            total_records_read += records_read;
648            self.buffer_offset += levels_read;
649            self.has_partial = partial;
650        }
651        Ok((total_records_read, total_levels_read))
652    }
653
654    fn skip_rep_levels(&mut self, num_records: usize, num_levels: usize) -> Result<(usize, usize)> {
655        let mut total_records_read = 0;
656        let mut total_levels_read = 0;
657
658        while total_records_read < num_records && total_levels_read < num_levels {
659            if self.buffer_len == self.buffer_offset {
660                self.fill_buf()?;
661                if self.buffer_len == 0 {
662                    break;
663                }
664            }
665
666            let (partial, records_read, levels_read) = self.count_records(
667                num_records - total_records_read,
668                num_levels - total_levels_read,
669            );
670
671            total_levels_read += levels_read;
672            total_records_read += records_read;
673            self.buffer_offset += levels_read;
674            self.has_partial = partial;
675        }
676        Ok((total_records_read, total_levels_read))
677    }
678
679    fn flush_partial(&mut self) -> bool {
680        std::mem::take(&mut self.has_partial)
681    }
682}
683
684#[cfg(test)]
685mod tests {
686    use super::*;
687    use crate::encodings::rle::RleEncoder;
688    use rand::{prelude::*, rng};
689
690    #[test]
691    fn fixed_len_payload_validation() {
692        let mut rng = StdRng::seed_from_u64(11262);
693        for page in ["dictionary page", "PLAIN data page"] {
694            for width in [0, 1, 4, 8, 16, 32] {
695                for count in [0, 1, 2, 33] {
696                    let raw: Bytes = (0..width * count).map(|_| rng.random::<u8>()).collect();
697                    let result =
698                        normalize_fixed_len_byte_array_payload(raw.clone(), count, width, page)
699                            .unwrap();
700                    assert_eq!(result, raw);
701                    assert_eq!(
702                        result.as_ptr(),
703                        raw.as_ptr(),
704                        "canonical data must stay zero-copy"
705                    );
706                }
707            }
708            // These are two canonical values, not one length-prefixed value.
709            let raw = Bytes::from_static(b"\x04\0\0\0abcd");
710            assert_eq!(
711                normalize_fixed_len_byte_array_payload(raw.clone(), 2, 4, page).unwrap(),
712                raw
713            );
714            // Truncated and trailing data must still be rejected.
715            for data in [b"abcdefg".as_slice(), b"abcdefghi"] {
716                assert!(
717                    normalize_fixed_len_byte_array_payload(
718                        Bytes::copy_from_slice(data),
719                        2,
720                        4,
721                        page
722                    )
723                    .is_err()
724                );
725            }
726            assert!(
727                normalize_fixed_len_byte_array_payload(Bytes::from_static(b"x"), 0, 4, page)
728                    .is_err()
729            );
730            assert!(
731                normalize_fixed_len_byte_array_payload(Bytes::new(), 1, usize::MAX, page).is_err()
732            );
733            let err = normalize_fixed_len_byte_array_payload(Bytes::new(), usize::MAX, 2, page)
734                .unwrap_err()
735                .to_string();
736            assert!(err.contains("payload size overflow"), "{err}");
737            assert!(err.contains(page), "{err}");
738        }
739    }
740
741    #[test]
742    fn fixed_len_other_encodings_unchanged() {
743        // No compatibility interpretation applies to other encodings.
744        for encoding in [
745            Encoding::DELTA_BYTE_ARRAY,
746            Encoding::BYTE_STREAM_SPLIT,
747            Encoding::RLE_DICTIONARY,
748        ] {
749            let data = Bytes::from_static(b"\x04\0\0\0abcd");
750            let (actual_encoding, actual) =
751                normalize_fixed_len_byte_array_data(data.clone(), 1, 4, encoding).unwrap();
752            assert_eq!(actual_encoding, encoding);
753            assert_eq!(actual.as_ptr(), data.as_ptr());
754            assert_eq!(actual, data);
755        }
756    }
757
758    #[test]
759    #[expect(deprecated, reason = "Cover legacy BIT_PACKED definition levels")]
760    fn test_skip_def_levels() {
761        use crate::util::bit_util::BitWriter;
762
763        // A multiple of eight avoids ambiguous padding in the final packed run.
764        let num_levels = 2056;
765        for max_level in [1, 2, 3, 7, 255, 32767] {
766            let bit_width = num_required_bits(max_level as u64);
767            for levels in [
768                vec![0; num_levels],
769                vec![max_level; num_levels],
770                (0..num_levels)
771                    .map(|i| (i % (max_level as usize + 1)) as i16)
772                    .collect(),
773            ] {
774                for encoding in [Encoding::RLE, Encoding::BIT_PACKED] {
775                    let data = match encoding {
776                        Encoding::RLE => {
777                            let mut encoder = RleEncoder::new(bit_width, 1024);
778                            for &level in &levels {
779                                encoder.put(level as u64);
780                            }
781                            Bytes::from(encoder.consume())
782                        }
783                        Encoding::BIT_PACKED => {
784                            let mut encoder = BitWriter::new(num_levels);
785                            for &level in &levels {
786                                encoder.put_value(level as u64, bit_width as usize);
787                            }
788                            Bytes::from(encoder.consume())
789                        }
790                        _ => unreachable!(),
791                    };
792                    for requested in [
793                        0,
794                        1,
795                        63,
796                        64,
797                        65,
798                        1023,
799                        1024,
800                        1025,
801                        num_levels,
802                        num_levels + 17,
803                        usize::MAX,
804                    ] {
805                        let mut decoder = DefinitionLevelDecoderImpl::new(max_level);
806                        decoder.set_data(encoding, data.clone()).unwrap();
807                        let expected_levels = requested.min(num_levels);
808                        let expected_values = levels[..expected_levels]
809                            .iter()
810                            .filter(|&&level| level == max_level)
811                            .count();
812                        assert_eq!(
813                            decoder.skip_def_levels(requested).unwrap(),
814                            (expected_values, expected_levels),
815                            "{encoding}, max_level={max_level}, requested={requested}"
816                        );
817
818                        let mut remaining = vec![];
819                        let expected_remaining = &levels[expected_levels..];
820                        assert_eq!(
821                            decoder
822                                .read_def_levels(&mut remaining, expected_remaining.len())
823                                .unwrap(),
824                            (
825                                expected_remaining
826                                    .iter()
827                                    .filter(|&&level| level == max_level)
828                                    .count(),
829                                expected_remaining.len(),
830                            )
831                        );
832                        assert_eq!(remaining, expected_remaining);
833                        assert_eq!(decoder.skip_def_levels(1).unwrap(), (0, 0));
834                    }
835                }
836            }
837        }
838    }
839
840    #[test]
841    fn test_skip_padding() {
842        let mut encoder = RleEncoder::new(1, 1024);
843        encoder.put(0);
844        (0..3).for_each(|_| encoder.put(1));
845        let data = Bytes::from(encoder.consume());
846
847        let mut decoder = RepetitionLevelDecoderImpl::new(1);
848        decoder.set_data(Encoding::RLE, data.clone()).unwrap();
849        let (_, levels) = decoder.skip_rep_levels(100, 4).unwrap();
850        assert_eq!(levels, 4);
851
852        // The length of the final bit packed run is ambiguous, so without the correct
853        // levels limit, it will decode zero padding
854        let mut decoder = RepetitionLevelDecoderImpl::new(1);
855        decoder.set_data(Encoding::RLE, data).unwrap();
856        let (_, levels) = decoder.skip_rep_levels(100, 6).unwrap();
857        assert_eq!(levels, 6);
858    }
859
860    #[test]
861    #[cfg_attr(miri, ignore)] // Takes too long
862    fn test_count_levels_eq() {
863        let chunk = u16::MAX as usize;
864        for len in [0, 1, chunk, chunk + 1, 3 * chunk + 7] {
865            assert_eq!(count_levels_eq(&vec![2; len], 2), len);
866
867            let levels: Vec<i16> = (0..len).map(|i| (i % 3) as i16).collect();
868            let expected = levels.iter().filter(|l| **l == 1).count();
869            assert_eq!(count_levels_eq(&levels, 1), expected);
870        }
871    }
872
873    #[test]
874    #[cfg_attr(miri, ignore)] // Takes too long
875    fn test_skip_rep_levels() {
876        for _ in 0..10 {
877            let mut rng = rng();
878            let total_len = 10000_usize;
879            // Records of random lengths, mostly short in some iterations and
880            // mostly long in others
881            let new_record = rng.random_range(0.01..0.5);
882            let mut encoded: Vec<i16> = (0..total_len)
883                .map(|_| {
884                    if rng.random_bool(new_record) {
885                        0
886                    } else {
887                        rng.random_range(1..5)
888                    }
889                })
890                .collect();
891            encoded[0] = 0;
892            let mut encoder = RleEncoder::new(3, 1024);
893            for v in &encoded {
894                encoder.put(*v as _)
895            }
896            let data = Bytes::from(encoder.consume());
897
898            let mut decoder = RepetitionLevelDecoderImpl::new(5);
899            decoder.set_data(Encoding::RLE, data).unwrap();
900
901            let total_records = encoded.iter().filter(|x| **x == 0).count();
902            let mut remaining_records = total_records;
903            let mut remaining_levels = encoded.len();
904            loop {
905                let skip = rng.random_bool(0.5);
906                // Mix reads of a few records with reads of many records
907                let max_records = if rng.random_bool(0.5) { 5 } else { 500 };
908                let records = rng.random_range(1..=remaining_records.min(max_records));
909                let (records_read, levels_read) = if skip {
910                    decoder.skip_rep_levels(records, remaining_levels).unwrap()
911                } else {
912                    let mut decoded = Vec::new();
913                    let (records_read, levels_read) = decoder
914                        .read_rep_levels(&mut decoded, records, remaining_levels)
915                        .unwrap();
916
917                    assert_eq!(
918                        decoded,
919                        encoded[encoded.len() - remaining_levels..][..levels_read]
920                    );
921                    (records_read, levels_read)
922                };
923
924                remaining_levels = remaining_levels.checked_sub(levels_read).unwrap();
925                if remaining_levels == 0 {
926                    assert_eq!(records_read + 1, records);
927                    assert_eq!(records, remaining_records);
928                    break;
929                }
930                assert_eq!(records_read, records);
931                remaining_records -= records;
932                assert_ne!(remaining_records, 0);
933            }
934        }
935    }
936}