Skip to main content

parquet/column/
reader.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
18//! Contains column reader API.
19
20use bytes::Bytes;
21
22use super::page::{Page, PageReader};
23use crate::basic::*;
24use crate::column::reader::decoder::{
25    ColumnValueDecoder, ColumnValueDecoderImpl, DefinitionLevelDecoder, DefinitionLevelDecoderImpl,
26    RepetitionLevelDecoder, RepetitionLevelDecoderImpl, normalize_fixed_len_byte_array_data,
27    prepare_v1_fixed_len_byte_array,
28};
29use crate::data_type::*;
30use crate::errors::{ParquetError, Result};
31use crate::schema::types::ColumnDescPtr;
32use crate::util::bit_util::{ceil, num_required_bits, read_num_bytes};
33
34pub(crate) mod decoder;
35mod legacy_fixed_len_byte_array;
36
37/// Column reader for a Parquet type.
38pub enum ColumnReader {
39    /// Column reader for boolean type
40    BoolColumnReader(ColumnReaderImpl<BoolType>),
41    /// Column reader for int32 type
42    Int32ColumnReader(ColumnReaderImpl<Int32Type>),
43    /// Column reader for int64 type
44    Int64ColumnReader(ColumnReaderImpl<Int64Type>),
45    /// Column reader for int96 type
46    Int96ColumnReader(ColumnReaderImpl<Int96Type>),
47    /// Column reader for float type
48    FloatColumnReader(ColumnReaderImpl<FloatType>),
49    /// Column reader for double type
50    DoubleColumnReader(ColumnReaderImpl<DoubleType>),
51    /// Column reader for byte array type
52    ByteArrayColumnReader(ColumnReaderImpl<ByteArrayType>),
53    /// Column reader for fixed length byte array type
54    FixedLenByteArrayColumnReader(ColumnReaderImpl<FixedLenByteArrayType>),
55}
56
57/// Gets a specific column reader corresponding to column descriptor `col_descr`. The
58/// column reader will read from pages in `col_page_reader`.
59pub fn get_column_reader(
60    col_descr: ColumnDescPtr,
61    col_page_reader: Box<dyn PageReader>,
62) -> ColumnReader {
63    match col_descr.physical_type() {
64        Type::BOOLEAN => {
65            ColumnReader::BoolColumnReader(ColumnReaderImpl::new(col_descr, col_page_reader))
66        }
67        Type::INT32 => {
68            ColumnReader::Int32ColumnReader(ColumnReaderImpl::new(col_descr, col_page_reader))
69        }
70        Type::INT64 => {
71            ColumnReader::Int64ColumnReader(ColumnReaderImpl::new(col_descr, col_page_reader))
72        }
73        Type::INT96 => {
74            ColumnReader::Int96ColumnReader(ColumnReaderImpl::new(col_descr, col_page_reader))
75        }
76        Type::FLOAT => {
77            ColumnReader::FloatColumnReader(ColumnReaderImpl::new(col_descr, col_page_reader))
78        }
79        Type::DOUBLE => {
80            ColumnReader::DoubleColumnReader(ColumnReaderImpl::new(col_descr, col_page_reader))
81        }
82        Type::BYTE_ARRAY => {
83            ColumnReader::ByteArrayColumnReader(ColumnReaderImpl::new(col_descr, col_page_reader))
84        }
85        Type::FIXED_LEN_BYTE_ARRAY => ColumnReader::FixedLenByteArrayColumnReader(
86            ColumnReaderImpl::new(col_descr, col_page_reader),
87        ),
88    }
89}
90
91/// Gets a typed column reader for the specific type `T`, by "up-casting" `col_reader` of
92/// non-generic type to a generic column reader type `ColumnReaderImpl`.
93///
94/// # Panics
95///
96/// Panics if actual enum value for `col_reader` does not match the type `T`.
97pub fn get_typed_column_reader<T: DataType>(col_reader: ColumnReader) -> ColumnReaderImpl<T> {
98    T::get_column_reader(col_reader).unwrap_or_else(|| {
99        panic!(
100            "Failed to convert column reader into a typed column reader for `{}` type",
101            T::get_physical_type()
102        )
103    })
104}
105
106/// Typed value reader for a particular primitive column.
107pub type ColumnReaderImpl<T> = GenericColumnReader<
108    RepetitionLevelDecoderImpl,
109    DefinitionLevelDecoderImpl,
110    ColumnValueDecoderImpl<T>,
111>;
112
113/// Reads data for a given column chunk, using the provided decoders:
114///
115/// - R: `ColumnLevelDecoder` used to decode repetition levels
116/// - D: `ColumnLevelDecoder` used to decode definition levels
117/// - V: `ColumnValueDecoder` used to decode value data
118pub struct GenericColumnReader<R, D, V> {
119    descr: ColumnDescPtr,
120
121    page_reader: Box<dyn PageReader>,
122
123    /// The total number of values stored in the data page.
124    num_buffered_values: usize,
125
126    /// The number of values from the current data page that has been decoded into memory
127    /// so far.
128    num_decoded_values: usize,
129
130    /// True if the end of the current data page denotes the end of a record
131    has_record_delimiter: bool,
132
133    /// The decoder for the definition levels if any
134    def_level_decoder: Option<D>,
135
136    /// The decoder for the repetition levels if any
137    rep_level_decoder: Option<R>,
138
139    /// The decoder for the values
140    values_decoder: V,
141
142    /// Width and remaining payload bytes for a nullable V1 FLBA page whose
143    /// physical count is checked during normal level decoding, not a pre-scan.
144    remaining_fixed_len_bytes: Option<(usize, usize)>,
145}
146
147impl<V> GenericColumnReader<RepetitionLevelDecoderImpl, DefinitionLevelDecoderImpl, V>
148where
149    V: ColumnValueDecoder,
150{
151    /// Creates new column reader based on column descriptor and page reader.
152    pub fn new(descr: ColumnDescPtr, page_reader: Box<dyn PageReader>) -> Self {
153        let values_decoder = V::new(&descr);
154
155        let def_level_decoder = (descr.max_def_level() != 0)
156            .then(|| DefinitionLevelDecoderImpl::new(descr.max_def_level()));
157
158        let rep_level_decoder = (descr.max_rep_level() != 0)
159            .then(|| RepetitionLevelDecoderImpl::new(descr.max_rep_level()));
160
161        Self::new_with_decoders(
162            descr,
163            page_reader,
164            values_decoder,
165            def_level_decoder,
166            rep_level_decoder,
167        )
168    }
169}
170
171impl<R, D, V> GenericColumnReader<R, D, V>
172where
173    R: RepetitionLevelDecoder,
174    D: DefinitionLevelDecoder,
175    V: ColumnValueDecoder,
176{
177    pub(crate) fn new_with_decoders(
178        descr: ColumnDescPtr,
179        page_reader: Box<dyn PageReader>,
180        values_decoder: V,
181        def_level_decoder: Option<D>,
182        rep_level_decoder: Option<R>,
183    ) -> Self {
184        Self {
185            descr,
186            def_level_decoder,
187            rep_level_decoder,
188            page_reader,
189            num_buffered_values: 0,
190            num_decoded_values: 0,
191            values_decoder,
192            has_record_delimiter: false,
193            remaining_fixed_len_bytes: None,
194        }
195    }
196
197    /// Read up to `max_records` whole records, returning the number of complete
198    /// records, non-null values and levels decoded. All levels for a given record
199    /// will be read, i.e. the next repetition level, if any, will be 0
200    ///
201    /// If the max definition level is 0, `def_levels` will be ignored and the number of records,
202    /// non-null values and levels decoded will all be equal, otherwise `def_levels` will be
203    /// populated with the number of levels read, with an error returned if it is `None`.
204    ///
205    /// If the max repetition level is 0, `rep_levels` will be ignored and the number of records
206    /// and levels decoded will both be equal, otherwise `rep_levels` will be populated with
207    /// the number of levels read, with an error returned if it is `None`.
208    ///
209    /// `values` will be contiguously populated with the non-null values. Note that if the column
210    /// is not required, this may be less than either `max_records` or the number of levels read.
211    ///
212    /// Nullable V1 FLBA payload sizes may be validated incrementally. Extra values or
213    /// truncated levels can therefore be reported only when the rest of a page is consumed.
214    /// Pages that could require legacy PLAIN repair are still validated eagerly.
215    pub fn read_records(
216        &mut self,
217        max_records: usize,
218        def_levels: Option<&mut D::Buffer>,
219        rep_levels: Option<&mut R::Buffer>,
220        values: &mut V::Buffer,
221    ) -> Result<(usize, usize, usize)> {
222        self.read_records_with_reservation(
223            max_records,
224            def_levels,
225            rep_levels,
226            values,
227            |_, _, _, _| Ok(()),
228        )
229    }
230
231    /// Like [`Self::read_records`], but invokes `reserve_values` after levels
232    /// are decoded and before values are read.
233    pub(crate) fn read_records_with_reservation<F>(
234        &mut self,
235        max_records: usize,
236        mut def_levels: Option<&mut D::Buffer>,
237        mut rep_levels: Option<&mut R::Buffer>,
238        values: &mut V::Buffer,
239        mut reserve_values: F,
240    ) -> Result<(usize, usize, usize)>
241    where
242        F: FnMut(&mut V::Buffer, usize, usize, Option<&D::Buffer>) -> Result<()>,
243    {
244        let mut total_records_read = 0;
245        let mut total_levels_read = 0;
246        let mut total_values_read = 0;
247
248        while total_records_read < max_records && self.has_next()? {
249            let remaining_records = max_records - total_records_read;
250            let remaining_levels = self.num_buffered_values - self.num_decoded_values;
251
252            let (records_read, levels_to_read) = match self.rep_level_decoder.as_mut() {
253                Some(reader) => {
254                    let out = rep_levels
255                        .as_mut()
256                        .ok_or_else(|| general_err!("must specify repetition levels"))?;
257
258                    let (mut records_read, levels_read) =
259                        reader.read_rep_levels(out, remaining_records, remaining_levels)?;
260
261                    if records_read == 0 && levels_read == 0 {
262                        // The fact that we're still looping implies there must be some levels to read.
263                        return Err(general_err!(
264                            "Insufficient repetition levels read from column"
265                        ));
266                    }
267                    if levels_read == remaining_levels && self.has_record_delimiter {
268                        check_partial_record_fits(records_read, remaining_records)?;
269                        records_read += reader.flush_partial() as usize;
270                    }
271                    (records_read, levels_read)
272                }
273                None => {
274                    let min = remaining_records.min(remaining_levels);
275                    (min, min)
276                }
277            };
278
279            let values_to_read = match self.def_level_decoder.as_mut() {
280                Some(reader) => {
281                    let out = def_levels
282                        .as_mut()
283                        .ok_or_else(|| general_err!("must specify definition levels"))?;
284
285                    let (values_read, levels_read) = reader.read_def_levels(out, levels_to_read)?;
286
287                    if levels_read != levels_to_read {
288                        return Err(general_err!(
289                            "insufficient definition levels read from column - expected {levels_to_read}, got {levels_read}"
290                        ));
291                    }
292
293                    values_read
294                }
295                None => levels_to_read,
296            };
297
298            self.check_fixed_len_bytes(values_to_read, levels_to_read == remaining_levels)?;
299
300            let def_levels = def_levels.as_deref();
301            reserve_values(values, values_to_read, levels_to_read, def_levels)?;
302
303            let values_read = self.values_decoder.read(values, values_to_read)?;
304
305            if values_read != values_to_read {
306                return Err(general_err!(
307                    "insufficient values read from column - expected: {values_to_read}, got: {values_read}",
308                ));
309            }
310
311            self.num_decoded_values += levels_to_read;
312            total_records_read += records_read;
313            total_levels_read += levels_to_read;
314            total_values_read += values_read;
315        }
316
317        Ok((total_records_read, total_values_read, total_levels_read))
318    }
319
320    /// Skips over `num_records` records, where records are delimited by repetition levels of 0
321    ///
322    /// # Returns
323    ///
324    /// Returns the number of records skipped
325    pub fn skip_records(&mut self, num_records: usize) -> Result<usize> {
326        let mut remaining_records = num_records;
327        while remaining_records != 0 {
328            if self.num_buffered_values == self.num_decoded_values {
329                let Some(metadata) = self.page_reader.peek_next_page()? else {
330                    return Ok(num_records - remaining_records);
331                };
332
333                // Defer dictionary decoding when the page reader can recover it later.
334                // Otherwise, preserve the eager behavior required by existing readers.
335                if metadata.is_dict {
336                    if self.page_reader.supports_deferred_dictionary() {
337                        self.page_reader.skip_next_page()?;
338                    } else {
339                        self.read_dictionary_page()?;
340                    }
341                    continue;
342                }
343
344                // If page has less rows than the remaining records to
345                // be skipped, skip entire page
346                let rows = metadata.num_rows.or_else(|| {
347                    // If no repetition levels, num_levels == num_rows
348                    self.rep_level_decoder
349                        .is_none()
350                        .then_some(metadata.num_levels)?
351                });
352
353                if let Some(rows) = rows
354                    && rows <= remaining_records
355                {
356                    self.page_reader.skip_next_page()?;
357                    remaining_records -= rows;
358                    continue;
359                }
360                // because self.num_buffered_values == self.num_decoded_values means
361                // we need reads a new page and set up the decoders for levels
362                if !self.read_new_page()? {
363                    return Ok(num_records - remaining_records);
364                }
365            }
366
367            // start skip values in page level
368
369            // The number of levels in the current data page
370            let remaining_levels = self.num_buffered_values - self.num_decoded_values;
371
372            let (records_read, rep_levels_read) = match self.rep_level_decoder.as_mut() {
373                Some(decoder) => {
374                    let (mut records_read, levels_read) =
375                        decoder.skip_rep_levels(remaining_records, remaining_levels)?;
376
377                    if levels_read == remaining_levels && self.has_record_delimiter {
378                        check_partial_record_fits(records_read, remaining_records)?;
379                        records_read += decoder.flush_partial() as usize;
380                    }
381
382                    (records_read, levels_read)
383                }
384                None => {
385                    // No repetition levels, so each level corresponds to a row
386                    let levels = remaining_levels.min(remaining_records);
387                    (levels, levels)
388                }
389            };
390
391            self.num_decoded_values += rep_levels_read;
392            remaining_records -= records_read;
393
394            let page_finished = self.num_buffered_values == self.num_decoded_values;
395            if page_finished && self.remaining_fixed_len_bytes.is_none() {
396                // Exhausted buffered page - no need to advance other decoders
397                continue;
398            }
399
400            let (values_read, def_levels_read) = match self.def_level_decoder.as_mut() {
401                Some(decoder) => decoder.skip_def_levels(rep_levels_read)?,
402                None => (rep_levels_read, rep_levels_read),
403            };
404
405            if rep_levels_read != def_levels_read {
406                return Err(general_err!(
407                    "levels mismatch, read {} repetition levels and {} definition levels",
408                    rep_levels_read,
409                    def_levels_read
410                ));
411            }
412
413            self.check_fixed_len_bytes(values_read, page_finished)?;
414            if page_finished {
415                continue;
416            }
417
418            let values = self.values_decoder.skip_values(values_read)?;
419            if values != values_read {
420                return Err(general_err!(
421                    "skipped {} values, expected {}",
422                    values,
423                    values_read
424                ));
425            }
426        }
427        Ok(num_records - remaining_records)
428    }
429
430    /// Account for actual physical values decoded or skipped from definition levels.
431    /// The payload length is a byte budget, not evidence of the expected value count.
432    fn check_fixed_len_bytes(&mut self, values: usize, page_finished: bool) -> Result<()> {
433        if let Some((width, remaining)) = self.remaining_fixed_len_bytes.as_mut() {
434            let bytes = values
435                .checked_mul(*width)
436                .ok_or_else(|| general_err!("FIXED_LEN_BYTE_ARRAY payload size overflow"))?;
437            let left = remaining.checked_sub(bytes).ok_or_else(|| {
438                general_err!(
439                    "Invalid FIXED_LEN_BYTE_ARRAY PLAIN data page payload length: \
440                     need {bytes} value bytes, only {remaining} remain"
441                )
442            })?;
443            if page_finished && left != 0 {
444                return Err(general_err!(
445                    "Invalid FIXED_LEN_BYTE_ARRAY PLAIN data page payload length: \
446                     {left} trailing value bytes"
447                ));
448            }
449            *remaining = left;
450            if page_finished {
451                self.remaining_fixed_len_bytes = None;
452            }
453        }
454        Ok(())
455    }
456
457    /// Reads the next page as a dictionary page and installs it.
458    ///
459    /// Used on the skip path for readers that do not retain skipped
460    /// dictionaries, and so must consume the page through `get_next_page`
461    /// while it is still available. Returns an error if the next page is not
462    /// a dictionary page.
463    fn read_dictionary_page(&mut self) -> Result<()> {
464        match self.page_reader.get_next_page()? {
465            Some(Page::DictionaryPage {
466                buf,
467                num_values,
468                encoding,
469                is_sorted,
470            }) => self
471                .values_decoder
472                .set_dict(buf, num_values, encoding, is_sorted),
473            _ => Err(ParquetError::General(
474                "Invalid page. Expecting dictionary page".to_string(),
475            )),
476        }
477    }
478
479    /// Installs a dictionary previously deferred by the page reader.
480    /// A no-op when nothing was deferred.
481    fn install_deferred_dictionary(&mut self) -> Result<()> {
482        match self.page_reader.take_deferred_dictionary()? {
483            Some(Page::DictionaryPage {
484                buf,
485                num_values,
486                encoding,
487                is_sorted,
488            }) => self
489                .values_decoder
490                .set_dict(buf, num_values, encoding, is_sorted),
491            Some(_) => Err(ParquetError::General(
492                "Invalid page. Expecting dictionary page".to_string(),
493            )),
494            None => Ok(()),
495        }
496    }
497
498    /// Reads a new page and set up the decoders for levels, values or dictionary.
499    /// Returns false if there's no page left.
500    fn read_new_page(&mut self) -> Result<bool> {
501        loop {
502            match self.page_reader.get_next_page()? {
503                // No more page to read
504                None => return Ok(false),
505                Some(current_page) => {
506                    match current_page {
507                        // 1. Dictionary page: configure dictionary for this page.
508                        Page::DictionaryPage {
509                            buf,
510                            num_values,
511                            encoding,
512                            is_sorted,
513                        } => {
514                            self.values_decoder
515                                .set_dict(buf, num_values, encoding, is_sorted)?;
516                        }
517                        // 2. Data page v1
518                        Page::DataPage {
519                            buf,
520                            num_values,
521                            encoding,
522                            def_level_encoding,
523                            rep_level_encoding,
524                            statistics: _,
525                        } => {
526                            if matches!(
527                                encoding,
528                                Encoding::PLAIN_DICTIONARY | Encoding::RLE_DICTIONARY
529                            ) {
530                                self.install_deferred_dictionary()?;
531                            }
532                            self.num_buffered_values = num_values as _;
533                            self.num_decoded_values = 0;
534
535                            let max_rep_level = self.descr.max_rep_level();
536                            let max_def_level = self.descr.max_def_level();
537                            self.remaining_fixed_len_bytes = None;
538
539                            let mut offset = 0;
540
541                            if max_rep_level > 0 {
542                                let (bytes_read, level_data) = parse_v1_level(
543                                    max_rep_level,
544                                    num_values,
545                                    rep_level_encoding,
546                                    buf.slice(offset..),
547                                )?;
548                                offset += bytes_read;
549
550                                self.has_record_delimiter =
551                                    self.page_reader.at_record_boundary()?;
552
553                                self.rep_level_decoder
554                                    .as_mut()
555                                    .unwrap()
556                                    .set_data(rep_level_encoding, level_data)?;
557                            }
558
559                            let definition_levels = if max_def_level > 0 {
560                                let (bytes_read, level_data) = parse_v1_level(
561                                    max_def_level,
562                                    num_values,
563                                    def_level_encoding,
564                                    buf.slice(offset..),
565                                )?;
566                                offset += bytes_read;
567                                Some(level_data)
568                            } else {
569                                None
570                            };
571
572                            let data = buf.slice(offset..);
573                            let (encoding, data) =
574                                if self.descr.physical_type() == Type::FIXED_LEN_BYTE_ARRAY {
575                                    let width = self.descr.type_length() as usize;
576                                    let page = prepare_v1_fixed_len_byte_array(
577                                        data,
578                                        num_values as usize,
579                                        width,
580                                        encoding,
581                                        definition_levels.as_ref().map(|levels| {
582                                            (max_def_level, def_level_encoding, levels)
583                                        }),
584                                    )?;
585                                    self.remaining_fixed_len_bytes =
586                                        page.validate_count.then_some((width, page.data.len()));
587                                    (page.encoding, page.data)
588                                } else {
589                                    (encoding, data)
590                                };
591                            if let Some(level_data) = definition_levels {
592                                self.def_level_decoder
593                                    .as_mut()
594                                    .unwrap()
595                                    .set_data(def_level_encoding, level_data)?;
596                            }
597                            self.values_decoder.set_data(
598                                encoding,
599                                data,
600                                num_values as usize,
601                                None,
602                            )?;
603                            return Ok(true);
604                        }
605                        // 3. Data page v2
606                        Page::DataPageV2 {
607                            buf,
608                            num_values,
609                            encoding,
610                            num_nulls,
611                            num_rows: _,
612                            def_levels_byte_len,
613                            rep_levels_byte_len,
614                            is_compressed: _,
615                            statistics: _,
616                        } => {
617                            if matches!(
618                                encoding,
619                                Encoding::PLAIN_DICTIONARY | Encoding::RLE_DICTIONARY
620                            ) {
621                                self.install_deferred_dictionary()?;
622                            }
623                            if num_nulls > num_values {
624                                return Err(general_err!(
625                                    "more nulls than values in page, contained {} values and {} nulls",
626                                    num_values,
627                                    num_nulls
628                                ));
629                            }
630
631                            self.num_buffered_values = num_values as _;
632                            self.num_decoded_values = 0;
633
634                            self.remaining_fixed_len_bytes = None;
635
636                            // DataPage v2 only supports RLE encoding for repetition
637                            // levels
638                            if self.descr.max_rep_level() > 0 {
639                                // Technically a DataPage v2 should not write a record
640                                // across multiple pages, however, the parquet writer
641                                // used to do this so we preserve backwards compatibility
642                                self.has_record_delimiter =
643                                    self.page_reader.at_record_boundary()?;
644
645                                self.rep_level_decoder.as_mut().unwrap().set_data(
646                                    Encoding::RLE,
647                                    buf.slice(..rep_levels_byte_len as usize),
648                                )?;
649                            }
650
651                            // DataPage v2 only supports RLE encoding for definition
652                            // levels
653                            if self.descr.max_def_level() > 0 {
654                                self.def_level_decoder.as_mut().unwrap().set_data(
655                                    Encoding::RLE,
656                                    buf.slice(
657                                        rep_levels_byte_len as usize
658                                            ..(rep_levels_byte_len + def_levels_byte_len) as usize,
659                                    ),
660                                )?;
661                            }
662
663                            let data =
664                                buf.slice((rep_levels_byte_len + def_levels_byte_len) as usize..);
665                            let (encoding, data) =
666                                if self.descr.physical_type() == Type::FIXED_LEN_BYTE_ARRAY {
667                                    normalize_fixed_len_byte_array_data(
668                                        data,
669                                        (num_values - num_nulls) as usize,
670                                        self.descr.type_length() as usize,
671                                        encoding,
672                                    )?
673                                } else {
674                                    (encoding, data)
675                                };
676                            self.values_decoder.set_data(
677                                encoding,
678                                data,
679                                num_values as usize,
680                                Some((num_values - num_nulls) as usize),
681                            )?;
682                            return Ok(true);
683                        }
684                    }
685                }
686            }
687        }
688    }
689
690    /// Check whether there is more data to read from this column,
691    /// If the current page is fully decoded, this will load the next page
692    /// (if it exists) into the buffer
693    #[inline]
694    pub(crate) fn has_next(&mut self) -> Result<bool> {
695        if self.num_buffered_values == 0 || self.num_buffered_values == self.num_decoded_values {
696            // TODO: should we return false if read_new_page() = true and
697            // num_buffered_values = 0?
698            if !self.read_new_page()? {
699                Ok(false)
700            } else {
701                Ok(self.num_buffered_values != 0)
702            }
703        } else {
704            Ok(true)
705        }
706    }
707}
708
709/// Checks that a partial record can still be flushed into the caller's record budget.
710///
711/// Reaching the end of a page with a record delimiter means the decoder stopped because
712/// it ran out of levels, not records, so it cannot have used up the whole budget. A page
713/// whose repetition levels disagree with its record count breaks that, and flushing the
714/// partial record would then take the count past what was asked for.
715fn check_partial_record_fits(records_read: usize, remaining_records: usize) -> Result<()> {
716    if remaining_records <= records_read {
717        return Err(general_err!(
718            "page ended after {records_read} record(s), which is already all of the \
719             {remaining_records} record(s) asked for, so there is no partial record to flush"
720        ));
721    }
722    Ok(())
723}
724
725fn parse_v1_level(
726    max_level: i16,
727    num_buffered_values: u32,
728    encoding: Encoding,
729    buf: Bytes,
730) -> Result<(usize, Bytes)> {
731    match encoding {
732        Encoding::RLE => {
733            let i32_size = std::mem::size_of::<i32>();
734            if i32_size <= buf.len() {
735                let data_size = read_num_bytes::<i32>(i32_size, buf.as_ref()) as usize;
736                let end = i32_size
737                    .checked_add(data_size)
738                    .ok_or(general_err!("invalid level length"))?;
739                if end <= buf.len() {
740                    return Ok((end, buf.slice(i32_size..end)));
741                }
742            }
743            Err(general_err!("not enough data to read levels"))
744        }
745        #[expect(deprecated)]
746        Encoding::BIT_PACKED => {
747            let bit_width = num_required_bits(max_level as u64);
748            let num_bytes = ceil(num_buffered_values as usize * bit_width as usize, 8);
749            Ok((num_bytes, buf.slice(..num_bytes)))
750        }
751        _ => Err(general_err!("invalid level encoding: {}", encoding)),
752    }
753}
754
755#[cfg(test)]
756mod tests {
757    use super::*;
758
759    use rand::distr::uniform::SampleUniform;
760    use std::{collections::VecDeque, sync::Arc};
761
762    use crate::basic::Type as PhysicalType;
763    use crate::schema::types::{ColumnDescriptor, ColumnPath, Type as SchemaType};
764    use crate::util::test_common::page_util::InMemoryPageReader;
765    use crate::util::test_common::rand_gen::make_pages;
766
767    pub(super) fn nullable_fixed_page(def: &[i16], encoding: Encoding, payload: &[u8]) -> Page {
768        use crate::encodings::levels::LevelEncoder;
769        let mut levels = LevelEncoder::v1_streaming(1);
770        levels.put_with_observer(def, |_, _| {});
771        let mut buf = levels.consume();
772        buf.extend_from_slice(payload);
773        Page::DataPage {
774            buf: buf.into(),
775            num_values: def.len() as u32,
776            encoding,
777            def_level_encoding: Encoding::RLE,
778            rep_level_encoding: Encoding::RLE,
779            statistics: None,
780        }
781    }
782
783    pub(super) fn nullable_fixed_reader(
784        pages: Vec<Page>,
785    ) -> ColumnReaderImpl<FixedLenByteArrayType> {
786        let descr = Arc::new(ColumnDescriptor::new(
787            Arc::new(
788                SchemaType::primitive_type_builder("fixed", PhysicalType::FIXED_LEN_BYTE_ARRAY)
789                    .with_length(4)
790                    .build()
791                    .unwrap(),
792            ),
793            1,
794            0,
795            ColumnPath::from("fixed"),
796        ));
797        ColumnReaderImpl::<FixedLenByteArrayType>::new(
798            descr,
799            Box::new(InMemoryPageReader::new(pages)),
800        )
801    }
802
803    /// These read/skip assertions apply to both canonical and normalized values.
804    pub(super) fn check_incremental_fixed_len_byte_array_pages(
805        encoding: Encoding,
806        payload: impl Fn(usize) -> Vec<u8>,
807    ) {
808        for count in [1, 2, 3] {
809            for finish_by_skipping in [false, true] {
810                let mut reader = nullable_fixed_reader(vec![nullable_fixed_page(
811                    &[1, 0, 1, 0],
812                    encoding,
813                    &payload(count),
814                )]);
815                let mut values = vec![];
816                assert_eq!(
817                    reader
818                        .read_records(1, Some(&mut vec![]), None, &mut values)
819                        .unwrap(),
820                    (1, 1, 1)
821                );
822                // Count-dependent corruption can be detected after the first
823                // value, regardless of the original value representation.
824                assert_eq!(values[0].data(), b"abcd");
825                assert_eq!(reader.remaining_fixed_len_bytes, Some((4, (count - 1) * 4)));
826                assert_eq!(reader.skip_records(1).unwrap(), 1);
827                let result = if finish_by_skipping {
828                    reader.skip_records(2).map(|_| ())
829                } else {
830                    reader
831                        .read_records(2, Some(&mut vec![]), None, &mut values)
832                        .map(|_| ())
833                };
834                if count == 2 {
835                    result.unwrap();
836                    assert!(reader.remaining_fixed_len_bytes.is_none());
837                } else {
838                    assert!(result.unwrap_err().to_string().contains("payload length"));
839                }
840            }
841        }
842    }
843
844    #[test]
845    fn fixed_v1_incremental_count_validation() {
846        check_incremental_fixed_len_byte_array_pages(Encoding::PLAIN, |n| b"abcd".repeat(n));
847
848        // Finishing by skipping checks both missing and extra values, including
849        // an all-null page with an unexpected whole value in its payload.
850        for last in [0, 1] {
851            for payload in [b"".as_slice(), b"abcd".as_slice()] {
852                let mut reader = nullable_fixed_reader(vec![nullable_fixed_page(
853                    &[0, 0, 0, last],
854                    Encoding::PLAIN,
855                    payload,
856                )]);
857                let mut values = vec![];
858                assert_eq!(
859                    reader
860                        .read_records(1, Some(&mut vec![]), None, &mut values)
861                        .unwrap(),
862                    (1, 0, 1)
863                );
864                assert_eq!(
865                    reader.skip_records(3).is_ok(),
866                    payload.len() == last as usize * 4
867                );
868                assert!(values.is_empty());
869            }
870        }
871    }
872
873    #[test]
874    fn fixed_v1_canonical_prefix_shaped_values() {
875        // Ten canonical values look exactly like five length-prefixed values.
876        let raw = 4_u32.to_le_bytes().repeat(10);
877        let mut reader =
878            nullable_fixed_reader(vec![nullable_fixed_page(&[1; 10], Encoding::PLAIN, &raw)]);
879        let mut values = vec![];
880        assert_eq!(
881            reader
882                .read_records(1, Some(&mut vec![]), None, &mut values)
883                .unwrap(),
884            (1, 1, 1)
885        );
886        reader
887            .read_records(usize::MAX, Some(&mut vec![]), None, &mut values)
888            .unwrap();
889        assert_eq!(values.len(), 10);
890        assert!(values.iter().all(|v| v.data() == 4_u32.to_le_bytes()));
891    }
892
893    #[test]
894    fn fixed_v1_incremental_page_transitions_and_short_levels() {
895        let first = nullable_fixed_page(&[1, 0, 1, 0], Encoding::PLAIN, b"abcdabcd");
896        let second = nullable_fixed_page(&[1, 1], Encoding::PLAIN, b"efghefgh");
897        let mut reader = nullable_fixed_reader(vec![first.clone(), second]);
898        let mut values = vec![];
899        reader
900            .read_records(1, Some(&mut vec![]), None, &mut values)
901            .unwrap();
902        assert_eq!(reader.skip_records(3).unwrap(), 3);
903        assert!(reader.remaining_fixed_len_bytes.is_none());
904        assert_eq!(
905            reader
906                .read_records(usize::MAX, Some(&mut vec![]), None, &mut values)
907                .unwrap(),
908            (2, 2, 2)
909        );
910        assert_eq!(
911            values.iter().map(|v| v.data()).collect::<Vec<_>>(),
912            [b"abcd", b"efgh", b"efgh"]
913        );
914
915        let mut short_levels = first;
916        if let Page::DataPage { num_values, .. } = &mut short_levels {
917            *num_values += 8; // exceed any packed padding
918        }
919        let mut reader = nullable_fixed_reader(vec![short_levels]);
920        reader
921            .read_records(1, Some(&mut vec![]), None, &mut vec![])
922            .unwrap();
923        let err = reader
924            .read_records(usize::MAX, Some(&mut vec![]), None, &mut vec![])
925            .unwrap_err();
926        assert!(err.to_string().contains("definition levels"));
927    }
928
929    #[test]
930    fn fixed_plain_payload_length_validation() {
931        check_fixed_len_byte_array_pages(
932            |raw| vec![(Encoding::PLAIN, raw.to_vec())],
933            |raw| {
934                let mut extra = raw.to_vec();
935                extra.push(0);
936                let mut malformed = vec![extra];
937                if !raw.is_empty() {
938                    malformed.push(raw[..raw.len() - 1].to_vec());
939                }
940                malformed
941            },
942        );
943    }
944
945    /// Shared page/level assertions, independent of the value representation.
946    /// Keeping the canonical test separate lets it survive removal of legacy support.
947    #[expect(deprecated, reason = "Cover legacy BIT_PACKED definition levels")]
948    pub(super) fn check_fixed_len_byte_array_pages(
949        payloads: impl Fn(&[u8]) -> Vec<(Encoding, Vec<u8>)>,
950        malformed_plain: impl Fn(&[u8]) -> Vec<Vec<u8>>,
951    ) {
952        use crate::encodings::levels::LevelEncoder;
953        use crate::encodings::rle::RleEncoder;
954        use crate::util::bit_util::BitWriter;
955
956        fn levels(data: &[i16], max: i16, v2: bool, encoding: Encoding) -> Vec<u8> {
957            if max == 0 {
958                return vec![];
959            }
960            if encoding == Encoding::BIT_PACKED {
961                let mut encoder = BitWriter::new(data.len());
962                for &value in data {
963                    encoder.put_value(value as u64, num_required_bits(max as u64) as usize);
964                }
965                return encoder.consume();
966            }
967            let mut encoder = if v2 {
968                LevelEncoder::v2_streaming(max)
969            } else {
970                LevelEncoder::v1_streaming(max)
971            };
972            encoder.put_with_observer(data, |_, _| {});
973            encoder.consume()
974        }
975
976        for (max_def, def, rep) in [
977            (0, vec![], vec![]),
978            (1, vec![1, 0, 1, 0, 1], vec![]),
979            (1, vec![0; 5], vec![]),
980            // Null parents, empty containers, null elements and repeated values.
981            (3, vec![0, 1, 2, 3, 3, 1, 3], vec![0, 0, 0, 1, 1, 0, 1]),
982            // Exercise counting across multiple bounded definition-level batches.
983            (
984                1,
985                (0..2051).map(|i| i16::from(i % 3 == 0)).collect(),
986                vec![],
987            ),
988        ] {
989            let max_rep = i16::from(!rep.is_empty());
990            let num_levels = if max_def == 0 { 3 } else { def.len() };
991            let num_values = if max_def == 0 {
992                num_levels
993            } else {
994                def.iter().filter(|&&v| v == max_def).count()
995            };
996            let num_rows = if max_rep == 0 {
997                num_levels
998            } else {
999                rep.iter().filter(|&&v| v == 0).count()
1000            };
1001            let desc = Arc::new(ColumnDescriptor::new(
1002                Arc::new(
1003                    SchemaType::primitive_type_builder("fixed", PhysicalType::FIXED_LEN_BYTE_ARRAY)
1004                        .with_length(4)
1005                        .build()
1006                        .unwrap(),
1007                ),
1008                max_def,
1009                max_rep,
1010                ColumnPath::from("fixed"),
1011            ));
1012            let raw: Vec<u8> = b"\x04\0\0\0\xff\xff\xff\xffabcd"
1013                .as_chunks::<4>()
1014                .0
1015                .iter()
1016                .cycle()
1017                .take(num_values)
1018                .flatten()
1019                .copied()
1020                .collect();
1021            let malformed = malformed_plain(&raw);
1022
1023            for (v2, level_encoding) in [
1024                (false, Encoding::RLE),
1025                (false, Encoding::BIT_PACKED),
1026                (true, Encoding::RLE),
1027            ] {
1028                let rep_data = levels(&rep, max_rep, v2, level_encoding);
1029                let def_data = levels(&def, max_def, v2, level_encoding);
1030                let make_page = |encoding, payload: &[u8]| {
1031                    let mut buf = rep_data.clone();
1032                    buf.extend_from_slice(&def_data);
1033                    buf.extend_from_slice(payload);
1034                    if v2 {
1035                        Page::DataPageV2 {
1036                            buf: Bytes::from(buf),
1037                            num_values: num_levels as u32,
1038                            encoding,
1039                            num_nulls: (num_levels - num_values) as u32,
1040                            num_rows: num_rows as u32,
1041                            def_levels_byte_len: def_data.len() as u32,
1042                            rep_levels_byte_len: rep_data.len() as u32,
1043                            is_compressed: false,
1044                            statistics: None,
1045                        }
1046                    } else {
1047                        Page::DataPage {
1048                            buf: Bytes::from(buf),
1049                            num_values: num_levels as u32,
1050                            encoding,
1051                            def_level_encoding: level_encoding,
1052                            rep_level_encoding: level_encoding,
1053                            statistics: None,
1054                        }
1055                    }
1056                };
1057                let make_reader = |pages| {
1058                    ColumnReaderImpl::<FixedLenByteArrayType>::new(
1059                        desc.clone(),
1060                        Box::new(InMemoryPageReader::new(pages)),
1061                    )
1062                };
1063                for (encoding, payload) in payloads(&raw) {
1064                    let payload = payload.as_slice();
1065                    let mut reader = make_reader(vec![make_page(encoding, payload)]);
1066                    let (mut values, mut actual_def, mut actual_rep) = (vec![], vec![], vec![]);
1067                    assert_eq!(
1068                        reader
1069                            .read_records(
1070                                usize::MAX,
1071                                Some(&mut actual_def),
1072                                Some(&mut actual_rep),
1073                                &mut values
1074                            )
1075                            .unwrap(),
1076                        (num_rows, num_values, num_levels)
1077                    );
1078                    assert_eq!(actual_def, def);
1079                    assert_eq!(actual_rep, rep);
1080                    assert_eq!(
1081                        values.iter().map(|v| v.data()).collect::<Vec<_>>(),
1082                        raw.as_chunks::<4>().0.iter().collect::<Vec<_>>()
1083                    );
1084
1085                    let first_record_levels = if max_rep == 0 {
1086                        1
1087                    } else {
1088                        rep.iter().skip(1).position(|&v| v == 0).unwrap() + 1
1089                    };
1090                    let first_record_values = if max_def == 0 {
1091                        1
1092                    } else {
1093                        def[..first_record_levels]
1094                            .iter()
1095                            .filter(|&&v| v == max_def)
1096                            .count()
1097                    };
1098                    let mut reader = make_reader(vec![make_page(encoding, payload)]);
1099                    assert_eq!(reader.skip_records(1).unwrap(), 1);
1100                    let mut values = vec![];
1101                    reader
1102                        .read_records(
1103                            usize::MAX,
1104                            Some(&mut vec![]),
1105                            Some(&mut vec![]),
1106                            &mut values,
1107                        )
1108                        .unwrap();
1109                    assert_eq!(
1110                        values.iter().map(|v| v.data()).collect::<Vec<_>>(),
1111                        raw[first_record_values * 4..]
1112                            .as_chunks::<4>()
1113                            .0
1114                            .iter()
1115                            .collect::<Vec<_>>()
1116                    );
1117                }
1118
1119                if !v2 && max_def != 0 && level_encoding == Encoding::RLE {
1120                    let mut page = make_page(Encoding::PLAIN, &raw);
1121                    if let Page::DataPage { num_values, .. } = &mut page {
1122                        // Exceed even the final bit-packed run's padding.
1123                        *num_values += 8;
1124                    }
1125                    // Incremental V1 validation detects missing levels when
1126                    // the page is consumed, not necessarily on the first row.
1127                    let err = make_reader(vec![page])
1128                        .read_records(
1129                            usize::MAX,
1130                            Some(&mut vec![]),
1131                            Some(&mut vec![]),
1132                            &mut vec![],
1133                        )
1134                        .unwrap_err()
1135                        .to_string();
1136                    assert!(
1137                        err.contains("definition levels")
1138                            || (max_rep != 0 && err.contains("repetition levels")),
1139                        "{err}"
1140                    );
1141                }
1142
1143                for payload in &malformed {
1144                    // Byte-alignment errors remain eager. Nullable V1 errors
1145                    // requiring the physical count can be delayed until page end.
1146                    for skip in [false, true] {
1147                        let mut reader = make_reader(vec![make_page(Encoding::PLAIN, payload)]);
1148                        let mut values = vec![];
1149                        let mut result = if skip {
1150                            reader.skip_records(1).map(|_| ())
1151                        } else {
1152                            reader
1153                                .read_records(1, Some(&mut vec![]), Some(&mut vec![]), &mut values)
1154                                .map(|_| ())
1155                        };
1156                        let provisional_values = values.len();
1157                        if result.is_err() {
1158                            assert!(values.is_empty());
1159                        } else {
1160                            assert!(!v2 && max_def != 0);
1161                            result = if skip {
1162                                reader.skip_records(usize::MAX).map(|_| ())
1163                            } else {
1164                                reader
1165                                    .read_records(
1166                                        usize::MAX,
1167                                        Some(&mut vec![]),
1168                                        Some(&mut vec![]),
1169                                        &mut values,
1170                                    )
1171                                    .map(|_| ())
1172                            };
1173                        }
1174                        let err = result.unwrap_err().to_string();
1175                        assert!(
1176                            err.contains(
1177                                "Invalid FIXED_LEN_BYTE_ARRAY PLAIN data page payload length"
1178                            ),
1179                            "v2={v2} {level_encoding} max_def={max_def} skip={skip}: {err}"
1180                        );
1181                        assert_eq!(values.len(), provisional_values);
1182                    }
1183
1184                    // A valid dictionary and dictionary-encoded page must not
1185                    // conceal malformed PLAIN data after dictionary fallback.
1186                    let mut indices = RleEncoder::new(1, 64);
1187                    for _ in 0..num_values {
1188                        indices.put(0);
1189                    }
1190                    let mut encoded = vec![1];
1191                    encoded.extend(indices.consume());
1192                    let mut reader = make_reader(vec![
1193                        Page::DictionaryPage {
1194                            buf: Bytes::from_static(b"abcd"),
1195                            num_values: 1,
1196                            encoding: Encoding::PLAIN,
1197                            is_sorted: false,
1198                        },
1199                        make_page(Encoding::RLE_DICTIONARY, &encoded),
1200                        make_page(Encoding::PLAIN, payload),
1201                    ]);
1202                    let mut values = vec![];
1203                    let err = reader
1204                        .read_records(
1205                            usize::MAX,
1206                            Some(&mut vec![]),
1207                            Some(&mut vec![]),
1208                            &mut values,
1209                        )
1210                        .unwrap_err()
1211                        .to_string();
1212                    assert!(err.contains("PLAIN data page payload length"), "{err}");
1213                    assert_eq!(values.len(), num_values);
1214                    assert!(values.iter().all(|v| v.data() == b"abcd"));
1215                }
1216            }
1217        }
1218    }
1219
1220    #[test]
1221    fn test_parse_v1_level_invalid_length() {
1222        // Say length is 10, but buffer is only 4
1223        let buf = Bytes::from(vec![10, 0, 0, 0]);
1224        let err = parse_v1_level(1, 100, Encoding::RLE, buf).unwrap_err();
1225        assert_eq!(
1226            err.to_string(),
1227            "Parquet error: not enough data to read levels"
1228        );
1229
1230        // Say length is 4, but buffer is only 3
1231        let buf = Bytes::from(vec![4, 0, 0]);
1232        let err = parse_v1_level(1, 100, Encoding::RLE, buf).unwrap_err();
1233        assert_eq!(
1234            err.to_string(),
1235            "Parquet error: not enough data to read levels"
1236        );
1237    }
1238
1239    const NUM_LEVELS: usize = 128;
1240    const NUM_PAGES: usize = 2;
1241    const MAX_DEF_LEVEL: i16 = 5;
1242    const MAX_REP_LEVEL: i16 = 5;
1243
1244    // Macro to generate test cases
1245    macro_rules! test {
1246        // branch for generating i32 cases
1247        ($test_func:ident, i32, $func:ident, $def_level:expr, $rep_level:expr,
1248     $num_pages:expr, $num_levels:expr, $batch_size:expr, $min:expr, $max:expr) => {
1249            test_internal!(
1250                $test_func,
1251                Int32Type,
1252                get_test_int32_type,
1253                $func,
1254                $def_level,
1255                $rep_level,
1256                $num_pages,
1257                $num_levels,
1258                $batch_size,
1259                $min,
1260                $max
1261            );
1262        };
1263        // branch for generating i64 cases
1264        ($test_func:ident, i64, $func:ident, $def_level:expr, $rep_level:expr,
1265     $num_pages:expr, $num_levels:expr, $batch_size:expr, $min:expr, $max:expr) => {
1266            test_internal!(
1267                $test_func,
1268                Int64Type,
1269                get_test_int64_type,
1270                $func,
1271                $def_level,
1272                $rep_level,
1273                $num_pages,
1274                $num_levels,
1275                $batch_size,
1276                $min,
1277                $max
1278            );
1279        };
1280    }
1281
1282    macro_rules! test_internal {
1283        ($test_func:ident, $ty:ident, $pty:ident, $func:ident, $def_level:expr,
1284     $rep_level:expr, $num_pages:expr, $num_levels:expr, $batch_size:expr,
1285     $min:expr, $max:expr) => {
1286            #[test]
1287            fn $test_func() {
1288                let desc = Arc::new(ColumnDescriptor::new(
1289                    Arc::new($pty()),
1290                    $def_level,
1291                    $rep_level,
1292                    ColumnPath::new(Vec::new()),
1293                ));
1294                let mut tester = ColumnReaderTester::<$ty>::new();
1295                tester.$func(desc, $num_pages, $num_levels, $batch_size, $min, $max);
1296            }
1297        };
1298    }
1299
1300    test!(
1301        test_read_plain_v1_int32,
1302        i32,
1303        plain_v1,
1304        MAX_DEF_LEVEL,
1305        MAX_REP_LEVEL,
1306        NUM_PAGES,
1307        NUM_LEVELS,
1308        16,
1309        i32::MIN,
1310        i32::MAX
1311    );
1312    test!(
1313        test_read_plain_v2_int32,
1314        i32,
1315        plain_v2,
1316        MAX_DEF_LEVEL,
1317        MAX_REP_LEVEL,
1318        NUM_PAGES,
1319        NUM_LEVELS,
1320        16,
1321        i32::MIN,
1322        i32::MAX
1323    );
1324
1325    test!(
1326        test_read_plain_v1_int32_uneven,
1327        i32,
1328        plain_v1,
1329        MAX_DEF_LEVEL,
1330        MAX_REP_LEVEL,
1331        NUM_PAGES,
1332        NUM_LEVELS,
1333        17,
1334        i32::MIN,
1335        i32::MAX
1336    );
1337    test!(
1338        test_read_plain_v2_int32_uneven,
1339        i32,
1340        plain_v2,
1341        MAX_DEF_LEVEL,
1342        MAX_REP_LEVEL,
1343        NUM_PAGES,
1344        NUM_LEVELS,
1345        17,
1346        i32::MIN,
1347        i32::MAX
1348    );
1349
1350    test!(
1351        test_read_plain_v1_int32_multi_page,
1352        i32,
1353        plain_v1,
1354        MAX_DEF_LEVEL,
1355        MAX_REP_LEVEL,
1356        NUM_PAGES,
1357        NUM_LEVELS,
1358        512,
1359        i32::MIN,
1360        i32::MAX
1361    );
1362    test!(
1363        test_read_plain_v2_int32_multi_page,
1364        i32,
1365        plain_v2,
1366        MAX_DEF_LEVEL,
1367        MAX_REP_LEVEL,
1368        NUM_PAGES,
1369        NUM_LEVELS,
1370        512,
1371        i32::MIN,
1372        i32::MAX
1373    );
1374
1375    // test cases when column descriptor has MAX_DEF_LEVEL = 0 and MAX_REP_LEVEL = 0
1376    test!(
1377        test_read_plain_v1_int32_required_non_repeated,
1378        i32,
1379        plain_v1,
1380        0,
1381        0,
1382        NUM_PAGES,
1383        NUM_LEVELS,
1384        16,
1385        i32::MIN,
1386        i32::MAX
1387    );
1388    test!(
1389        test_read_plain_v2_int32_required_non_repeated,
1390        i32,
1391        plain_v2,
1392        0,
1393        0,
1394        NUM_PAGES,
1395        NUM_LEVELS,
1396        16,
1397        i32::MIN,
1398        i32::MAX
1399    );
1400
1401    test!(
1402        test_read_plain_v1_int64,
1403        i64,
1404        plain_v1,
1405        1,
1406        1,
1407        NUM_PAGES,
1408        NUM_LEVELS,
1409        16,
1410        i64::MIN,
1411        i64::MAX
1412    );
1413    test!(
1414        test_read_plain_v2_int64,
1415        i64,
1416        plain_v2,
1417        1,
1418        1,
1419        NUM_PAGES,
1420        NUM_LEVELS,
1421        16,
1422        i64::MIN,
1423        i64::MAX
1424    );
1425
1426    test!(
1427        test_read_plain_v1_int64_uneven,
1428        i64,
1429        plain_v1,
1430        1,
1431        1,
1432        NUM_PAGES,
1433        NUM_LEVELS,
1434        17,
1435        i64::MIN,
1436        i64::MAX
1437    );
1438    test!(
1439        test_read_plain_v2_int64_uneven,
1440        i64,
1441        plain_v2,
1442        1,
1443        1,
1444        NUM_PAGES,
1445        NUM_LEVELS,
1446        17,
1447        i64::MIN,
1448        i64::MAX
1449    );
1450
1451    test!(
1452        test_read_plain_v1_int64_multi_page,
1453        i64,
1454        plain_v1,
1455        1,
1456        1,
1457        NUM_PAGES,
1458        NUM_LEVELS,
1459        512,
1460        i64::MIN,
1461        i64::MAX
1462    );
1463    test!(
1464        test_read_plain_v2_int64_multi_page,
1465        i64,
1466        plain_v2,
1467        1,
1468        1,
1469        NUM_PAGES,
1470        NUM_LEVELS,
1471        512,
1472        i64::MIN,
1473        i64::MAX
1474    );
1475
1476    // test cases when column descriptor has MAX_DEF_LEVEL = 0 and MAX_REP_LEVEL = 0
1477    test!(
1478        test_read_plain_v1_int64_required_non_repeated,
1479        i64,
1480        plain_v1,
1481        0,
1482        0,
1483        NUM_PAGES,
1484        NUM_LEVELS,
1485        16,
1486        i64::MIN,
1487        i64::MAX
1488    );
1489    test!(
1490        test_read_plain_v2_int64_required_non_repeated,
1491        i64,
1492        plain_v2,
1493        0,
1494        0,
1495        NUM_PAGES,
1496        NUM_LEVELS,
1497        16,
1498        i64::MIN,
1499        i64::MAX
1500    );
1501
1502    test!(
1503        test_read_dict_v1_int32_small,
1504        i32,
1505        dict_v1,
1506        MAX_DEF_LEVEL,
1507        MAX_REP_LEVEL,
1508        2,
1509        2,
1510        16,
1511        0,
1512        3
1513    );
1514    test!(
1515        test_read_dict_v2_int32_small,
1516        i32,
1517        dict_v2,
1518        MAX_DEF_LEVEL,
1519        MAX_REP_LEVEL,
1520        2,
1521        2,
1522        16,
1523        0,
1524        3
1525    );
1526
1527    test!(
1528        test_read_dict_v1_int32,
1529        i32,
1530        dict_v1,
1531        MAX_DEF_LEVEL,
1532        MAX_REP_LEVEL,
1533        NUM_PAGES,
1534        NUM_LEVELS,
1535        16,
1536        0,
1537        3
1538    );
1539    test!(
1540        test_read_dict_v2_int32,
1541        i32,
1542        dict_v2,
1543        MAX_DEF_LEVEL,
1544        MAX_REP_LEVEL,
1545        NUM_PAGES,
1546        NUM_LEVELS,
1547        16,
1548        0,
1549        3
1550    );
1551
1552    test!(
1553        test_read_dict_v1_int32_uneven,
1554        i32,
1555        dict_v1,
1556        MAX_DEF_LEVEL,
1557        MAX_REP_LEVEL,
1558        NUM_PAGES,
1559        NUM_LEVELS,
1560        17,
1561        0,
1562        3
1563    );
1564    test!(
1565        test_read_dict_v2_int32_uneven,
1566        i32,
1567        dict_v2,
1568        MAX_DEF_LEVEL,
1569        MAX_REP_LEVEL,
1570        NUM_PAGES,
1571        NUM_LEVELS,
1572        17,
1573        0,
1574        3
1575    );
1576
1577    test!(
1578        test_read_dict_v1_int32_multi_page,
1579        i32,
1580        dict_v1,
1581        MAX_DEF_LEVEL,
1582        MAX_REP_LEVEL,
1583        NUM_PAGES,
1584        NUM_LEVELS,
1585        512,
1586        0,
1587        3
1588    );
1589    test!(
1590        test_read_dict_v2_int32_multi_page,
1591        i32,
1592        dict_v2,
1593        MAX_DEF_LEVEL,
1594        MAX_REP_LEVEL,
1595        NUM_PAGES,
1596        NUM_LEVELS,
1597        512,
1598        0,
1599        3
1600    );
1601
1602    test!(
1603        test_read_dict_v1_int64,
1604        i64,
1605        dict_v1,
1606        MAX_DEF_LEVEL,
1607        MAX_REP_LEVEL,
1608        NUM_PAGES,
1609        NUM_LEVELS,
1610        16,
1611        0,
1612        3
1613    );
1614    test!(
1615        test_read_dict_v2_int64,
1616        i64,
1617        dict_v2,
1618        MAX_DEF_LEVEL,
1619        MAX_REP_LEVEL,
1620        NUM_PAGES,
1621        NUM_LEVELS,
1622        16,
1623        0,
1624        3
1625    );
1626
1627    #[test]
1628    fn test_read_batch_values_only() {
1629        test_read_batch_int32(16, 0, 0);
1630    }
1631
1632    #[test]
1633    fn test_read_batch_values_def_levels() {
1634        test_read_batch_int32(16, MAX_DEF_LEVEL, 0);
1635    }
1636
1637    #[test]
1638    fn test_read_batch_values_rep_levels() {
1639        test_read_batch_int32(16, 0, MAX_REP_LEVEL);
1640    }
1641
1642    #[test]
1643    fn test_read_batch_values_def_rep_levels() {
1644        test_read_batch_int32(128, MAX_DEF_LEVEL, MAX_REP_LEVEL);
1645    }
1646
1647    #[test]
1648    fn test_read_batch_adjust_after_buffering_page() {
1649        // This test covers scenario when buffering new page results in setting number
1650        // of decoded values to 0, resulting on reading `batch_size` of values, but it is
1651        // larger than we can insert into slice (affects values and levels).
1652        //
1653        // Note: values are chosen to reproduce the issue.
1654        //
1655        let primitive_type = get_test_int32_type();
1656        let desc = Arc::new(ColumnDescriptor::new(
1657            Arc::new(primitive_type),
1658            1,
1659            1,
1660            ColumnPath::new(Vec::new()),
1661        ));
1662
1663        let num_pages = 2;
1664        let num_levels = 4;
1665        let batch_size = 5;
1666
1667        let mut tester = ColumnReaderTester::<Int32Type>::new();
1668        tester.test_read_batch(
1669            desc,
1670            Encoding::RLE_DICTIONARY,
1671            num_pages,
1672            num_levels,
1673            batch_size,
1674            i32::MIN,
1675            i32::MAX,
1676            false,
1677        );
1678    }
1679
1680    // ----------------------------------------------------------------------
1681    // Helper methods to make pages and test
1682    //
1683    // # Overview
1684    //
1685    // Most of the test functionality is implemented in `ColumnReaderTester`, which
1686    // provides some general data page test methods:
1687    // - `test_read_batch_general`
1688    // - `test_read_batch`
1689    //
1690    // There are also some high level wrappers that are part of `ColumnReaderTester`:
1691    // - `plain_v1` -> call `test_read_batch_general` with data page v1 and plain encoding
1692    // - `plain_v2` -> call `test_read_batch_general` with data page v2 and plain encoding
1693    // - `dict_v1` -> call `test_read_batch_general` with data page v1 + dictionary page
1694    // - `dict_v2` -> call `test_read_batch_general` with data page v2 + dictionary page
1695    //
1696    // And even higher level wrappers that simplify testing of almost the same test cases:
1697    // - `get_test_int32_type`, provides dummy schema type
1698    // - `get_test_int64_type`, provides dummy schema type
1699    // - `test_read_batch_int32`, wrapper for `read_batch` tests, since they are basically
1700    //   the same, just different def/rep levels and batch size.
1701    //
1702    // # Page assembly
1703    //
1704    // Page construction and generation of values, definition and repetition levels
1705    // happens in `make_pages` function.
1706    // All values are randomly generated based on provided min/max, levels are calculated
1707    // based on provided max level for column descriptor (which is basically either int32
1708    // or int64 type in tests) and `levels_per_page` variable.
1709    //
1710    // We use `DataPageBuilder` and its implementation `DataPageBuilderImpl` to actually
1711    // turn values, definition and repetition levels into data pages (either v1 or v2).
1712    //
1713    // Those data pages are then stored as part of `TestPageReader` (we just pass vector
1714    // of generated pages directly), which implements `PageReader` interface.
1715    //
1716    // # Comparison
1717    //
1718    // This allows us to pass test page reader into column reader, so we can test
1719    // functionality of column reader - see `test_read_batch`, where we create column
1720    // reader -> typed column reader, buffer values in `read_batch` method and compare
1721    // output with generated data.
1722
1723    // Returns dummy Parquet `Type` for primitive field, because most of our tests use
1724    // INT32 physical type.
1725    fn get_test_int32_type() -> SchemaType {
1726        SchemaType::primitive_type_builder("a", PhysicalType::INT32)
1727            .with_repetition(Repetition::REQUIRED)
1728            .with_converted_type(ConvertedType::INT_32)
1729            .with_length(-1)
1730            .build()
1731            .expect("build() should be OK")
1732    }
1733
1734    // Returns dummy Parquet `Type` for INT64 physical type.
1735    fn get_test_int64_type() -> SchemaType {
1736        SchemaType::primitive_type_builder("a", PhysicalType::INT64)
1737            .with_repetition(Repetition::REQUIRED)
1738            .with_converted_type(ConvertedType::INT_64)
1739            .with_length(-1)
1740            .build()
1741            .expect("build() should be OK")
1742    }
1743
1744    // Tests `read_batch()` functionality for INT32.
1745    //
1746    // This is a high level wrapper on `ColumnReaderTester` that allows us to specify some
1747    // boilerplate code for setting up definition/repetition levels and column descriptor.
1748    fn test_read_batch_int32(batch_size: usize, max_def_level: i16, max_rep_level: i16) {
1749        let primitive_type = get_test_int32_type();
1750
1751        let desc = Arc::new(ColumnDescriptor::new(
1752            Arc::new(primitive_type),
1753            max_def_level,
1754            max_rep_level,
1755            ColumnPath::new(Vec::new()),
1756        ));
1757
1758        let mut tester = ColumnReaderTester::<Int32Type>::new();
1759        tester.test_read_batch(
1760            desc,
1761            Encoding::RLE_DICTIONARY,
1762            NUM_PAGES,
1763            NUM_LEVELS,
1764            batch_size,
1765            i32::MIN,
1766            i32::MAX,
1767            false,
1768        );
1769    }
1770
1771    struct ColumnReaderTester<T: DataType>
1772    where
1773        T::T: PartialOrd + SampleUniform + Copy,
1774    {
1775        rep_levels: Vec<i16>,
1776        def_levels: Vec<i16>,
1777        values: Vec<T::T>,
1778    }
1779
1780    impl<T: DataType> ColumnReaderTester<T>
1781    where
1782        T::T: PartialOrd + SampleUniform + Copy,
1783    {
1784        pub fn new() -> Self {
1785            Self {
1786                rep_levels: Vec::new(),
1787                def_levels: Vec::new(),
1788                values: Vec::new(),
1789            }
1790        }
1791
1792        // Method to generate and test data pages v1
1793        fn plain_v1(
1794            &mut self,
1795            desc: ColumnDescPtr,
1796            num_pages: usize,
1797            num_levels: usize,
1798            batch_size: usize,
1799            min: T::T,
1800            max: T::T,
1801        ) {
1802            self.test_read_batch_general(
1803                desc,
1804                Encoding::PLAIN,
1805                num_pages,
1806                num_levels,
1807                batch_size,
1808                min,
1809                max,
1810                false,
1811            );
1812        }
1813
1814        // Method to generate and test data pages v2
1815        fn plain_v2(
1816            &mut self,
1817            desc: ColumnDescPtr,
1818            num_pages: usize,
1819            num_levels: usize,
1820            batch_size: usize,
1821            min: T::T,
1822            max: T::T,
1823        ) {
1824            self.test_read_batch_general(
1825                desc,
1826                Encoding::PLAIN,
1827                num_pages,
1828                num_levels,
1829                batch_size,
1830                min,
1831                max,
1832                true,
1833            );
1834        }
1835
1836        // Method to generate and test dictionary page + data pages v1
1837        fn dict_v1(
1838            &mut self,
1839            desc: ColumnDescPtr,
1840            num_pages: usize,
1841            num_levels: usize,
1842            batch_size: usize,
1843            min: T::T,
1844            max: T::T,
1845        ) {
1846            self.test_read_batch_general(
1847                desc,
1848                Encoding::RLE_DICTIONARY,
1849                num_pages,
1850                num_levels,
1851                batch_size,
1852                min,
1853                max,
1854                false,
1855            );
1856        }
1857
1858        // Method to generate and test dictionary page + data pages v2
1859        fn dict_v2(
1860            &mut self,
1861            desc: ColumnDescPtr,
1862            num_pages: usize,
1863            num_levels: usize,
1864            batch_size: usize,
1865            min: T::T,
1866            max: T::T,
1867        ) {
1868            self.test_read_batch_general(
1869                desc,
1870                Encoding::RLE_DICTIONARY,
1871                num_pages,
1872                num_levels,
1873                batch_size,
1874                min,
1875                max,
1876                true,
1877            );
1878        }
1879
1880        // Helper function for the general case of `read_batch()` where `values`,
1881        // `def_levels` and `rep_levels` are always provided with enough space.
1882        #[expect(clippy::too_many_arguments)]
1883        fn test_read_batch_general(
1884            &mut self,
1885            desc: ColumnDescPtr,
1886            encoding: Encoding,
1887            num_pages: usize,
1888            num_levels: usize,
1889            batch_size: usize,
1890            min: T::T,
1891            max: T::T,
1892            use_v2: bool,
1893        ) {
1894            self.test_read_batch(
1895                desc, encoding, num_pages, num_levels, batch_size, min, max, use_v2,
1896            );
1897        }
1898
1899        // Helper function to test `read_batch()` method with custom buffers for values,
1900        // definition and repetition levels.
1901        #[expect(clippy::too_many_arguments)]
1902        fn test_read_batch(
1903            &mut self,
1904            desc: ColumnDescPtr,
1905            encoding: Encoding,
1906            num_pages: usize,
1907            num_levels: usize,
1908            batch_size: usize,
1909            min: T::T,
1910            max: T::T,
1911            use_v2: bool,
1912        ) {
1913            let mut pages = VecDeque::new();
1914            make_pages::<T>(
1915                desc.clone(),
1916                encoding,
1917                num_pages,
1918                num_levels,
1919                min,
1920                max,
1921                &mut self.def_levels,
1922                &mut self.rep_levels,
1923                &mut self.values,
1924                &mut pages,
1925                use_v2,
1926            );
1927            let max_def_level = desc.max_def_level();
1928            let max_rep_level = desc.max_rep_level();
1929            let page_reader = InMemoryPageReader::new(pages);
1930            let column_reader = get_column_reader(desc, Box::new(page_reader));
1931            let mut typed_column_reader = get_typed_column_reader::<T>(column_reader);
1932
1933            let mut values = Vec::new();
1934            let mut def_levels = Vec::new();
1935            let mut rep_levels = Vec::new();
1936
1937            let mut curr_values_read = 0;
1938            let mut curr_levels_read = 0;
1939            loop {
1940                let (_, values_read, levels_read) = typed_column_reader
1941                    .read_records(
1942                        batch_size,
1943                        Some(&mut def_levels),
1944                        Some(&mut rep_levels),
1945                        &mut values,
1946                    )
1947                    .expect("read_batch() should be OK");
1948
1949                curr_values_read += values_read;
1950                curr_levels_read += levels_read;
1951
1952                if values_read == 0 && levels_read == 0 {
1953                    break;
1954                }
1955            }
1956
1957            assert_eq!(values, self.values, "values content doesn't match");
1958
1959            if max_def_level > 0 {
1960                assert_eq!(
1961                    def_levels, self.def_levels,
1962                    "definition levels content doesn't match"
1963                );
1964            }
1965
1966            if max_rep_level > 0 {
1967                assert_eq!(
1968                    rep_levels, self.rep_levels,
1969                    "repetition levels content doesn't match"
1970                );
1971            }
1972
1973            assert!(
1974                curr_levels_read >= curr_values_read,
1975                "expected levels read to be greater than values read"
1976            );
1977        }
1978    }
1979
1980    /// Regression test for <https://github.com/apache/arrow-rs/issues/9370>
1981    ///
1982    /// Reproduces the production scenario: all DataPage v2 pages for a
1983    /// list column (rep_level=1) read without an offset index (i.e.
1984    /// `at_record_boundary` returns false for non-last pages).
1985    ///
1986    /// When a prior operation (here `skip_records(1)`) loads a v2 page,
1987    /// and a subsequent `skip_records` exhausts the remaining levels on
1988    /// that page, the rep level decoder is left with `has_partial=true`.
1989    /// Because `has_record_delimiter` is false, the partial is not
1990    /// flushed during level-based processing. When the next v2 page is
1991    /// then peeked with `num_rows` available, the whole-page-skip
1992    /// shortcut must flush the pending partial first. Otherwise:
1993    ///
1994    /// 1. The skip over-counts (skips N+1 records instead of N), and
1995    /// 2. The stale `has_partial` causes a subsequent `read_records` to
1996    ///    produce a "phantom" record with 0 values.
1997    #[test]
1998    fn test_skip_records_v2_page_skip_accounts_for_partial() {
1999        use crate::encodings::levels::LevelEncoder;
2000
2001        let max_rep_level: i16 = 1;
2002        let max_def_level: i16 = 1;
2003
2004        // Column descriptor for a list element column (rep=1, def=1)
2005        let primitive_type = SchemaType::primitive_type_builder("element", PhysicalType::INT32)
2006            .with_repetition(Repetition::REQUIRED)
2007            .build()
2008            .unwrap();
2009        let desc = Arc::new(ColumnDescriptor::new(
2010            Arc::new(primitive_type),
2011            max_def_level,
2012            max_rep_level,
2013            ColumnPath::new(vec!["list".to_string(), "element".to_string()]),
2014        ));
2015
2016        // Helper: build a DataPage v2 for this list column.
2017        let make_v2_page =
2018            |rep_levels: &[i16], def_levels: &[i16], values: &[i32], num_rows: u32| -> Page {
2019                let mut rep_enc = LevelEncoder::v2_streaming(max_rep_level);
2020                rep_enc.put_with_observer(rep_levels, |_, _| {});
2021                let rep_bytes = rep_enc.consume();
2022
2023                let mut def_enc = LevelEncoder::v2_streaming(max_def_level);
2024                def_enc.put_with_observer(def_levels, |_, _| {});
2025                let def_bytes = def_enc.consume();
2026
2027                let val_bytes: Vec<u8> = values.iter().flat_map(|v| v.to_le_bytes()).collect();
2028
2029                let mut buf = Vec::new();
2030                buf.extend_from_slice(&rep_bytes);
2031                buf.extend_from_slice(&def_bytes);
2032                buf.extend_from_slice(&val_bytes);
2033
2034                Page::DataPageV2 {
2035                    buf: Bytes::from(buf),
2036                    num_values: rep_levels.len() as u32,
2037                    encoding: Encoding::PLAIN,
2038                    num_nulls: 0,
2039                    num_rows,
2040                    def_levels_byte_len: def_bytes.len() as u32,
2041                    rep_levels_byte_len: rep_bytes.len() as u32,
2042                    is_compressed: false,
2043                    statistics: None,
2044                }
2045            };
2046
2047        // All pages are DataPage v2 (matching the production scenario where
2048        // parquet-rs writes only v2 data pages and no offset index is loaded,
2049        // so at_record_boundary() returns false for non-last pages).
2050
2051        // Page 1 (v2): 2 records × 2 elements = [10,20], [30,40]
2052        let page1 = make_v2_page(&[0, 1, 0, 1], &[1, 1, 1, 1], &[10, 20, 30, 40], 2);
2053
2054        // Page 2 (v2): 2 records × 2 elements = [50,60], [70,80]
2055        let page2 = make_v2_page(&[0, 1, 0, 1], &[1, 1, 1, 1], &[50, 60, 70, 80], 2);
2056
2057        // Page 3 (v2): 1 record × 2 elements = [90,100]
2058        let page3 = make_v2_page(&[0, 1], &[1, 1], &[90, 100], 1);
2059
2060        // 5 records total: [10,20], [30,40], [50,60], [70,80], [90,100]
2061        let pages = VecDeque::from(vec![page1, page2, page3]);
2062        let page_reader = InMemoryPageReader::new(pages);
2063        let column_reader = get_column_reader(desc, Box::new(page_reader));
2064        let mut typed_reader = get_typed_column_reader::<Int32Type>(column_reader);
2065
2066        // Step 1 — skip 1 record:
2067        //   Peek page 1: num_rows=2, remaining=1 → rows(2) > remaining(1),
2068        //   so the page is LOADED (not whole-page-skipped).
2069        //   Level-based skip consumes rep levels [0,1] for record [10,20],
2070        //   stopping at the 0 that starts record [30,40].
2071        let skipped = typed_reader.skip_records(1).unwrap();
2072        assert_eq!(skipped, 1);
2073
2074        // Step 2 — skip 2 more records ([30,40] and [50,60]):
2075        //   Mid-page in page 1 with 2 remaining levels [0,1] for [30,40].
2076        //   skip_rep_levels(2, 2): the leading 0 does NOT act as a record
2077        //   delimiter (has_partial=false, idx==0), so count_records returns
2078        //   (true, 0, 2) — all levels consumed, has_partial=true, 0 records.
2079        //
2080        //   has_record_delimiter is false → no flush at page boundary.
2081        //   Page 1 exhausted → peek page 2 (v2, num_rows=2).
2082        //
2083        //   With fix: flush_partial → remaining 2→1, page 2 NOT skipped
2084        //   (rows=2 > remaining=1). Load page 2, skip 1 record [50,60].
2085        //
2086        //   Without fix: rows(2) <= remaining(2) → page 2 whole-page-skipped,
2087        //   over-counting by 1. has_partial stays true (stale from page 1).
2088        let skipped = typed_reader.skip_records(2).unwrap();
2089        assert_eq!(skipped, 2);
2090
2091        // Step 3 — read 1 record:
2092        let mut values = Vec::new();
2093        let mut def_levels = Vec::new();
2094        let mut rep_levels = Vec::new();
2095
2096        let (records, values_read, levels_read) = typed_reader
2097            .read_records(1, Some(&mut def_levels), Some(&mut rep_levels), &mut values)
2098            .unwrap();
2099
2100        // Without the fix: (1, 0, 0) — phantom record from stale has_partial;
2101        //   the rep=0 on page 3 "completes" the phantom, yielding 0 values.
2102        // With the fix:    (1, 2, 2) — correctly reads record [70, 80].
2103        assert_eq!(records, 1, "should read exactly 1 record");
2104        assert_eq!(levels_read, 2, "should read 2 levels for the record");
2105        assert_eq!(values_read, 2, "should read 2 non-null values");
2106        assert_eq!(values, vec![70, 80], "should contain 4th record's values");
2107        assert_eq!(rep_levels, vec![0, 1], "rep levels for a 2-element list");
2108        assert_eq!(def_levels, vec![1, 1], "def levels (all non-null)");
2109    }
2110}