// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "parquet/encoding.h"

#include <algorithm>
#include <array>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <memory>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>

#include "arrow/array.h"
#include "arrow/array/builder_binary.h"
#include "arrow/array/builder_dict.h"
#include "arrow/array/builder_primitive.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit_block_counter.h"
#include "arrow/util/bit_run_reader.h"
#include "arrow/util/bit_stream_utils_internal.h"
#include "arrow/util/bit_util.h"
#include "arrow/util/bitmap_ops.h"
#include "arrow/util/byte_stream_split_internal.h"
#include "arrow/util/checked_cast.h"
#include "arrow/util/int_util_overflow.h"
#include "arrow/util/logging_internal.h"
#include "arrow/util/rle_encoding_internal.h"
#include "arrow/util/spaced_internal.h"
#include "arrow/util/ubsan.h"
#include "arrow/visit_data_inline.h"

#include "parquet/exception.h"
#include "parquet/platform.h"
#include "parquet/schema.h"
#include "parquet/types.h"

#ifdef _MSC_VER
// disable warning about inheritance via dominance in the diamond pattern
#  pragma warning(disable : 4250)
#endif

namespace bit_util = arrow::bit_util;

using arrow::Status;
using arrow::VisitNullBitmapInline;
using arrow::internal::AddWithOverflow;
using arrow::internal::BitBlockCounter;
using arrow::internal::checked_cast;
using arrow::internal::VisitBitRuns;
using arrow::util::SafeLoad;
using arrow::util::SafeLoadAs;

namespace parquet {
namespace {

// A helper class to abstract away differences between EncodingTraits<DType>::Accumulator
// for ByteArrayType and FLBAType.

template <typename DType, typename ArrowType>
struct ArrowBinaryHelper;

template <>
struct ArrowBinaryHelper<ByteArrayType, ::arrow::BinaryType> {
  using Accumulator = typename EncodingTraits<ByteArrayType>::Accumulator;

  explicit ArrowBinaryHelper(Accumulator* acc)
      : acc_(acc),
        builder_(checked_cast<::arrow::BinaryBuilder*>(acc->builder.get())),
        chunk_space_remaining_(::arrow::kBinaryMemoryLimit -
                               builder_->value_data_length()) {}

  // Prepare will reserve the number of entries in the current chunk.
  // If estimated_data_length is provided, it will also reserve the estimated data length.
  Status Prepare(int64_t length, std::optional<int64_t> estimated_data_length = {}) {
    entries_remaining_ = length;
    RETURN_NOT_OK(ReserveInitialChunkData(estimated_data_length));
    return Status::OK();
  }

  // If a new chunk is created and estimated_remaining_data_length is provided,
  // it will also reserve the estimated data length for this chunk.
  Status AppendValue(const uint8_t* data, int32_t length,
                     std::optional<int64_t> estimated_remaining_data_length = {}) {
    DCHECK_GT(entries_remaining_, 0);

    if (ARROW_PREDICT_FALSE(!CanFit(length))) {
      // This element would exceed the capacity of a chunk
      RETURN_NOT_OK(PushChunk());
      // Reserve entries and data in new chunk
      RETURN_NOT_OK(ReserveInitialChunkData(estimated_remaining_data_length));
    }
    chunk_space_remaining_ -= length;
    --entries_remaining_;
    if (estimated_remaining_data_length.has_value()) {
      // Assume Prepare() was already called with an estimated_data_length
      builder_->UnsafeAppend(data, length);
      return Status::OK();
    } else {
      return builder_->Append(data, length);
    }
  }

  void UnsafeAppendNull() {
    DCHECK_GT(entries_remaining_, 0);
    --entries_remaining_;
    builder_->UnsafeAppendNull();
  }

  Status AppendNulls(int64_t length) {
    DCHECK_GE(entries_remaining_, length);
    entries_remaining_ -= length;
    return builder_->AppendNulls(length);
  }

 private:
  Status PushChunk() {
    ARROW_ASSIGN_OR_RAISE(auto chunk, acc_->builder->Finish());
    acc_->chunks.push_back(std::move(chunk));
    chunk_space_remaining_ = ::arrow::kBinaryMemoryLimit;
    return Status::OK();
  }

  Status ReserveInitialChunkData(std::optional<int64_t> estimated_remaining_data_length) {
    RETURN_NOT_OK(builder_->Reserve(entries_remaining_));
    if (estimated_remaining_data_length.has_value()) {
      int64_t required_capacity =
          std::min(*estimated_remaining_data_length, chunk_space_remaining_);
      RETURN_NOT_OK(builder_->ReserveData(required_capacity));
    }
    return Status::OK();
  }

  bool CanFit(int64_t length) const { return length <= chunk_space_remaining_; }

  Accumulator* acc_;
  ::arrow::BinaryBuilder* builder_;
  int64_t entries_remaining_;
  int64_t chunk_space_remaining_;
};

template <typename ArrowBinaryType>
struct ArrowBinaryHelper<ByteArrayType, ArrowBinaryType> {
  using Accumulator = typename EncodingTraits<ByteArrayType>::Accumulator;
  using BuilderType = typename ::arrow::TypeTraits<ArrowBinaryType>::BuilderType;

  static constexpr bool kIsBinaryView =
      ::arrow::is_binary_view_like_type<ArrowBinaryType>::value;

  explicit ArrowBinaryHelper(Accumulator* acc)
      : builder_(checked_cast<BuilderType*>(acc->builder.get())) {}

  // Prepare will reserve the number of entries in the current chunk.
  // If estimated_data_length is provided, it will also reserve the estimated data length,
  // and the caller should better call `UnsafeAppend` instead of `Append` to avoid
  // double-checking the data length.
  Status Prepare(int64_t length, std::optional<int64_t> estimated_data_length = {}) {
    RETURN_NOT_OK(builder_->Reserve(length));
    // Avoid reserving data when reading into a binary-view array, because many
    // values may be very short and not require any heap storage, which would make
    // the initial allocation wasteful.
    if (!kIsBinaryView && estimated_data_length.has_value()) {
      RETURN_NOT_OK(builder_->ReserveData(*estimated_data_length));
    }
    return Status::OK();
  }

  Status AppendValue(const uint8_t* data, int32_t length,
                     std::optional<int64_t> estimated_remaining_data_length = {}) {
    if (!kIsBinaryView && estimated_remaining_data_length.has_value()) {
      // Assume Prepare() was already called with an estimated_data_length
      builder_->UnsafeAppend(data, length);
      return Status::OK();
    } else {
      return builder_->Append(data, length);
    }
  }

  void UnsafeAppendNull() { builder_->UnsafeAppendNull(); }

  Status AppendNulls(int64_t length) { return builder_->AppendNulls(length); }

 private:
  BuilderType* builder_;
};

template <>
struct ArrowBinaryHelper<FLBAType, ::arrow::FixedSizeBinaryType> {
  using Accumulator = typename EncodingTraits<FLBAType>::Accumulator;

  explicit ArrowBinaryHelper(Accumulator* acc) : acc_(acc) {}

  Status Prepare(int64_t length, std::optional<int64_t> estimated_data_length = {}) {
    return acc_->Reserve(length);
  }

  Status AppendValue(const uint8_t* data, int32_t length,
                     std::optional<int64_t> estimated_remaining_data_length = {}) {
    acc_->UnsafeAppend(data);
    return Status::OK();
  }

  void UnsafeAppendNull() { acc_->UnsafeAppendNull(); }

  Status AppendNulls(int64_t length) { return acc_->AppendNulls(length); }

 private:
  Accumulator* acc_;
};

// Call `func(&helper, args...)` where `helper` is a ArrowBinaryHelper<> instance
// suitable for the Parquet DType and accumulator `acc`.
template <typename DType, typename Function, typename... Args>
auto DispatchArrowBinaryHelper(typename EncodingTraits<DType>::Accumulator* acc,
                               int64_t length,
                               std::optional<int64_t> estimated_data_length,
                               Function&& func, Args&&... args) {
  static_assert(std::is_same_v<DType, ByteArrayType> || std::is_same_v<DType, FLBAType>,
                "unsupported DType");
  if constexpr (std::is_same_v<DType, ByteArrayType>) {
    switch (acc->builder->type()->id()) {
      case ::arrow::Type::BINARY:
      case ::arrow::Type::STRING: {
        ArrowBinaryHelper<DType, ::arrow::BinaryType> helper(acc);
        RETURN_NOT_OK(helper.Prepare(length, estimated_data_length));
        return func(&helper, std::forward<Args>(args)...);
      }
      case ::arrow::Type::LARGE_BINARY:
      case ::arrow::Type::LARGE_STRING: {
        ArrowBinaryHelper<DType, ::arrow::LargeBinaryType> helper(acc);
        RETURN_NOT_OK(helper.Prepare(length, estimated_data_length));
        return func(&helper, std::forward<Args>(args)...);
      }
      case ::arrow::Type::BINARY_VIEW:
      case ::arrow::Type::STRING_VIEW: {
        ArrowBinaryHelper<DType, ::arrow::BinaryViewType> helper(acc);
        RETURN_NOT_OK(helper.Prepare(length, estimated_data_length));
        return func(&helper, std::forward<Args>(args)...);
      }
      default:
        throw ParquetException(
            "Unsupported Arrow builder type when reading from BYTE_ARRAY column: " +
            acc->builder->type()->ToString());
    }
  } else {
    ArrowBinaryHelper<DType, ::arrow::FixedSizeBinaryType> helper(acc);
    RETURN_NOT_OK(helper.Prepare(length, estimated_data_length));
    return func(&helper, std::forward<Args>(args)...);
  }
}

void CheckPageLargeEnough(int64_t remaining_bytes, int32_t value_width,
                          int64_t num_values) {
  if (remaining_bytes < value_width * num_values) {
    ParquetException::EofException();
  }
}

// Internal decoder class hierarchy

class DecoderImpl : virtual public Decoder {
 public:
  void SetData(int num_values, const uint8_t* data, int len) override {
    num_values_ = num_values;
    data_ = data;
    len_ = len;
  }

  int values_left() const override { return num_values_; }
  Encoding::type encoding() const override { return encoding_; }

 protected:
  DecoderImpl(const ColumnDescriptor* descr, Encoding::type encoding)
      : descr_(descr), encoding_(encoding), num_values_(0), data_(NULLPTR), len_(0) {}

  // For accessing type-specific metadata, like FIXED_LEN_BYTE_ARRAY
  const ColumnDescriptor* descr_;

  const Encoding::type encoding_;
  int num_values_;
  const uint8_t* data_;
  int len_;
};

template <typename DType>
class TypedDecoderImpl : public DecoderImpl, virtual public TypedDecoder<DType> {
 public:
  using T = typename DType::c_type;

 protected:
  TypedDecoderImpl(const ColumnDescriptor* descr, Encoding::type encoding)
      : DecoderImpl(descr, encoding) {
    if constexpr (std::is_same_v<DType, FLBAType>) {
      if (descr_ == nullptr) {
        throw ParquetException(
            "Must pass a ColumnDescriptor when creating a Decoder for "
            "FIXED_LEN_BYTE_ARRAY");
      }
      type_length_ = descr_->type_length();
    } else if constexpr (std::is_same_v<DType, ByteArrayType>) {
      type_length_ = -1;
    } else {
      type_length_ = sizeof(T);
    }
  }

  int DecodeSpaced(T* buffer, int num_values, int null_count, const uint8_t* valid_bits,
                   int64_t valid_bits_offset) override {
    if (null_count > 0) {
      int values_to_read = num_values - null_count;
      int values_read = this->Decode(buffer, values_to_read);
      if (values_read != values_to_read) {
        throw ParquetException("Number of values / definition_levels read did not match");
      }
      ::arrow::util::internal::SpacedExpandRightward<T>(buffer, num_values, null_count,
                                                        valid_bits, valid_bits_offset);
      return num_values;
    } else {
      return this->Decode(buffer, num_values);
    }
  }

  int type_length_;
};

// ----------------------------------------------------------------------
// PLAIN decoder

template <typename DType>
class PlainDecoder : public TypedDecoderImpl<DType> {
 public:
  using T = typename DType::c_type;

  explicit PlainDecoder(const ColumnDescriptor* descr)
      : TypedDecoderImpl<DType>(descr, Encoding::PLAIN) {}

  int Decode(T* buffer, int max_values) override;

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<DType>::Accumulator* builder) override;

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<DType>::DictAccumulator* builder) override;
};

template <>
int PlainDecoder<Int96Type>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<Int96Type>::Accumulator* builder) {
  ParquetException::NYI("DecodeArrow not supported for Int96");
}

template <>
int PlainDecoder<Int96Type>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<Int96Type>::DictAccumulator* builder) {
  ParquetException::NYI("DecodeArrow not supported for Int96");
}

template <>
int PlainDecoder<BooleanType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<BooleanType>::Accumulator* builder) {
  ParquetException::NYI("BooleanType handled in concrete subclass");
}

template <>
int PlainDecoder<BooleanType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<BooleanType>::DictAccumulator* builder) {
  ParquetException::NYI("dictionaries of BooleanType");
}

template <typename DType>
int PlainDecoder<DType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<DType>::Accumulator* builder) {
  using value_type = typename DType::c_type;

  constexpr int value_size = static_cast<int>(sizeof(value_type));
  int values_decoded = num_values - null_count;
  CheckPageLargeEnough(this->len_, value_size, values_decoded);

  const uint8_t* data = this->data_;

  PARQUET_THROW_NOT_OK(builder->Reserve(num_values));
  PARQUET_THROW_NOT_OK(
      VisitBitRuns(valid_bits, valid_bits_offset, num_values,
                   [&](int64_t position, int64_t run_length, bool is_valid) {
                     if (is_valid) {
                       RETURN_NOT_OK(builder->AppendValues(
                           reinterpret_cast<const value_type*>(data), run_length));
                       data += run_length * sizeof(value_type);
                     } else {
                       RETURN_NOT_OK(builder->AppendNulls(run_length));
                     }
                     return Status::OK();
                   }));

  this->data_ = data;
  this->len_ -= sizeof(value_type) * values_decoded;
  this->num_values_ -= values_decoded;
  return values_decoded;
}

template <typename DType>
int PlainDecoder<DType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<DType>::DictAccumulator* builder) {
  using value_type = typename DType::c_type;

  constexpr int value_size = static_cast<int>(sizeof(value_type));
  int values_decoded = num_values - null_count;
  CheckPageLargeEnough(this->len_, value_size, values_decoded);

  const uint8_t* data = this->data_;

  PARQUET_THROW_NOT_OK(builder->Reserve(num_values));
  VisitNullBitmapInline(
      valid_bits, valid_bits_offset, num_values, null_count,
      [&]() {
        PARQUET_THROW_NOT_OK(builder->Append(SafeLoadAs<value_type>(data)));
        data += sizeof(value_type);
      },
      [&]() { PARQUET_THROW_NOT_OK(builder->AppendNull()); });

  this->data_ = data;
  this->len_ -= sizeof(value_type) * values_decoded;
  this->num_values_ -= values_decoded;
  return values_decoded;
}

// Decode routine templated on C++ type rather than type enum
template <typename T>
inline int DecodePlain(const uint8_t* data, int64_t data_size, int num_values,
                       int type_length, T* out) {
  int64_t bytes_to_decode = num_values * static_cast<int64_t>(sizeof(T));
  if (bytes_to_decode > data_size || bytes_to_decode > INT_MAX) {
    ParquetException::EofException();
  }
  // If bytes_to_decode == 0, data could be null
  if (bytes_to_decode > 0) {
    memcpy(out, data, static_cast<size_t>(bytes_to_decode));
  }
  return static_cast<int>(bytes_to_decode);
}

// Template specialization for BYTE_ARRAY. The written values do not own their
// own data.

static inline int64_t ReadByteArray(const uint8_t* data, int64_t data_size,
                                    ByteArray* out) {
  if (ARROW_PREDICT_FALSE(data_size < 4)) {
    ParquetException::EofException();
  }
  const int32_t len = SafeLoadAs<int32_t>(data);
  if (len < 0) {
    throw ParquetException("Invalid BYTE_ARRAY value");
  }
  const int64_t consumed_length = static_cast<int64_t>(len) + 4;
  if (ARROW_PREDICT_FALSE(data_size < consumed_length)) {
    ParquetException::EofException();
  }
  *out = ByteArray{static_cast<uint32_t>(len), data + 4};
  return consumed_length;
}

template <>
inline int DecodePlain<ByteArray>(const uint8_t* data, int64_t data_size, int num_values,
                                  int type_length, ByteArray* out) {
  int bytes_decoded = 0;
  for (int i = 0; i < num_values; ++i) {
    const auto increment = ReadByteArray(data, data_size, out + i);
    if (ARROW_PREDICT_FALSE(increment > INT_MAX - bytes_decoded)) {
      throw ParquetException("BYTE_ARRAY chunk too large");
    }
    data += increment;
    data_size -= increment;
    bytes_decoded += static_cast<int>(increment);
  }
  return bytes_decoded;
}

// Template specialization for FIXED_LEN_BYTE_ARRAY. The written values do not
// own their own data.
template <>
inline int DecodePlain<FixedLenByteArray>(const uint8_t* data, int64_t data_size,
                                          int num_values, int type_length,
                                          FixedLenByteArray* out) {
  int64_t bytes_to_decode = static_cast<int64_t>(type_length) * num_values;
  if (bytes_to_decode > data_size || bytes_to_decode > INT_MAX) {
    ParquetException::EofException();
  }
  for (int i = 0; i < num_values; ++i) {
    out[i].ptr = data + i * static_cast<int64_t>(type_length);
  }
  return static_cast<int>(bytes_to_decode);
}

template <typename DType>
int PlainDecoder<DType>::Decode(T* buffer, int max_values) {
  max_values = std::min(max_values, this->num_values_);
  int bytes_consumed =
      DecodePlain<T>(this->data_, this->len_, max_values, this->type_length_, buffer);
  this->data_ += bytes_consumed;
  this->len_ -= bytes_consumed;
  this->num_values_ -= max_values;
  return max_values;
}

// PLAIN decoder implementation for BOOLEAN

class PlainBooleanDecoder : public TypedDecoderImpl<BooleanType>, public BooleanDecoder {
 public:
  explicit PlainBooleanDecoder(const ColumnDescriptor* descr);
  void SetData(int num_values, const uint8_t* data, int len) override;

  // Two flavors of bool decoding
  int Decode(uint8_t* buffer, int max_values) override;
  int Decode(bool* buffer, int max_values) override;
  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<BooleanType>::Accumulator* out) override;

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<BooleanType>::DictAccumulator* out) override;

 private:
  std::unique_ptr<::arrow::bit_util::BitReader> bit_reader_;
  int total_num_values_{0};
};

PlainBooleanDecoder::PlainBooleanDecoder(const ColumnDescriptor* descr)
    : TypedDecoderImpl<BooleanType>(descr, Encoding::PLAIN) {}

void PlainBooleanDecoder::SetData(int num_values, const uint8_t* data, int len) {
  DecoderImpl::SetData(num_values, data, len);
  total_num_values_ = num_values;
  bit_reader_ = std::make_unique<bit_util::BitReader>(data, len);
}

int PlainBooleanDecoder::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<BooleanType>::Accumulator* builder) {
  int values_decoded = num_values - null_count;
  if (ARROW_PREDICT_FALSE(num_values_ < values_decoded)) {
    // A too large `num_values` was requested.
    ParquetException::EofException(
        "A too large `num_values` was requested in PlainBooleanDecoder: remain " +
        std::to_string(num_values_) + ", requested: " + std::to_string(values_decoded));
  }
  if (ARROW_PREDICT_FALSE(!bit_reader_->Advance(values_decoded))) {
    ParquetException::EofException("PlainDecoder doesn't have enough values in page");
  }

  if (null_count == 0) {
    // FastPath: can copy the data directly
    PARQUET_THROW_NOT_OK(builder->AppendValues(data_, values_decoded, NULLPTR,
                                               total_num_values_ - num_values_));
  } else {
    // Handle nulls by BitBlockCounter
    PARQUET_THROW_NOT_OK(builder->Reserve(num_values));
    BitBlockCounter bit_counter(valid_bits, valid_bits_offset, num_values);
    int64_t value_position = 0;
    int64_t valid_bits_offset_position = valid_bits_offset;
    int64_t previous_value_offset = total_num_values_ - num_values_;
    while (value_position < num_values) {
      auto block = bit_counter.NextWord();
      if (block.AllSet()) {
        // GH-40978: We don't have UnsafeAppendValues for booleans currently,
        // so using `AppendValues` here.
        PARQUET_THROW_NOT_OK(
            builder->AppendValues(data_, block.length, NULLPTR, previous_value_offset));
        previous_value_offset += block.length;
      } else if (block.NoneSet()) {
        // GH-40978: We don't have UnsafeAppendNulls for booleans currently,
        // so using `AppendNulls` here.
        PARQUET_THROW_NOT_OK(builder->AppendNulls(block.length));
      } else {
        for (int64_t i = 0; i < block.length; ++i) {
          if (bit_util::GetBit(valid_bits, valid_bits_offset_position + i)) {
            bool value = bit_util::GetBit(data_, previous_value_offset);
            builder->UnsafeAppend(value);
            previous_value_offset += 1;
          } else {
            builder->UnsafeAppendNull();
          }
        }
      }
      value_position += block.length;
      valid_bits_offset_position += block.length;
    }
  }

  num_values_ -= values_decoded;
  return values_decoded;
}

inline int PlainBooleanDecoder::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<BooleanType>::DictAccumulator* builder) {
  ParquetException::NYI("dictionaries of BooleanType");
}

int PlainBooleanDecoder::Decode(uint8_t* buffer, int max_values) {
  max_values = std::min(max_values, num_values_);
  if (ARROW_PREDICT_FALSE(!bit_reader_->Advance(max_values))) {
    ParquetException::EofException();
  }
  // Copy the data directly
  // Parquet's boolean encoding is bit-packed using LSB. So
  // we can directly copy the data to the buffer.
  ::arrow::internal::CopyBitmap(this->data_, /*offset=*/total_num_values_ - num_values_,
                                /*length=*/max_values, /*dest=*/buffer,
                                /*dest_offset=*/0);
  num_values_ -= max_values;
  return max_values;
}

int PlainBooleanDecoder::Decode(bool* buffer, int max_values) {
  max_values = std::min(max_values, num_values_);
  if (bit_reader_->GetBatch(1, buffer, max_values) != max_values) {
    ParquetException::EofException();
  }
  num_values_ -= max_values;
  return max_values;
}

// PLAIN decoder implementation for FIXED_LEN_BYTE_ARRAY and BYTE_ARRAY

template <>
inline int PlainDecoder<ByteArrayType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<ByteArrayType>::Accumulator* builder) {
  ParquetException::NYI();
}

template <>
inline int PlainDecoder<ByteArrayType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<ByteArrayType>::DictAccumulator* builder) {
  ParquetException::NYI();
}

template <>
inline int PlainDecoder<FLBAType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<FLBAType>::Accumulator* builder) {
  const int byte_width = this->type_length_;
  const int values_decoded = num_values - null_count;
  CheckPageLargeEnough(len_, byte_width, values_decoded);

  PARQUET_THROW_NOT_OK(builder->Reserve(num_values));

  // 1. Copy directly into the FixedSizeBinary data buffer, packed to the right.
  uint8_t* decode_out = builder->GetMutableValue(builder->length() + null_count);
  memcpy(decode_out, data_, values_decoded * byte_width);

  // 2. Expand the values into their final positions.
  if (null_count == 0) {
    // No expansion required, and no need to append the bitmap
    builder->UnsafeAdvance(num_values);
  } else {
    ::arrow::util::internal::SpacedExpandLeftward(
        builder->GetMutableValue(builder->length()), byte_width, num_values, null_count,
        valid_bits, valid_bits_offset);
    builder->UnsafeAdvance(num_values, valid_bits, valid_bits_offset);
  }
  data_ += byte_width * values_decoded;
  num_values_ -= values_decoded;
  len_ -= byte_width * values_decoded;
  return values_decoded;
}

template <>
inline int PlainDecoder<FLBAType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<FLBAType>::DictAccumulator* builder) {
  const int byte_width = this->type_length_;
  const int values_decoded = num_values - null_count;
  CheckPageLargeEnough(len_, byte_width, values_decoded);

  PARQUET_THROW_NOT_OK(builder->Reserve(num_values));
  PARQUET_THROW_NOT_OK(
      VisitBitRuns(valid_bits, valid_bits_offset, num_values,
                   [&](int64_t position, int64_t run_length, bool is_valid) {
                     if (is_valid) {
                       for (int64_t i = 0; i < run_length; ++i) {
                         RETURN_NOT_OK(builder->Append(data_));
                       }
                       data_ += run_length * byte_width;
                     } else {
                       RETURN_NOT_OK(builder->AppendNulls(run_length));
                     }
                     return Status::OK();
                   }));

  num_values_ -= values_decoded;
  len_ -= byte_width * values_decoded;
  return values_decoded;
}

class PlainByteArrayDecoder : public PlainDecoder<ByteArrayType> {
 public:
  using Base = PlainDecoder<ByteArrayType>;
  using Base::DecodeSpaced;
  using Base::PlainDecoder;

  // ----------------------------------------------------------------------
  // Dictionary read paths

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  ::arrow::BinaryDictionary32Builder* builder) override {
    int result = 0;
    PARQUET_THROW_NOT_OK(DecodeArrow(num_values, null_count, valid_bits,
                                     valid_bits_offset, builder, &result));
    return result;
  }

  // ----------------------------------------------------------------------
  // Optimized dense binary read paths

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<ByteArrayType>::Accumulator* out) override {
    int result = 0;
    PARQUET_THROW_NOT_OK(DecodeArrowDense(num_values, null_count, valid_bits,
                                          valid_bits_offset, out, &result));
    return result;
  }

 private:
  Status DecodeArrowDense(int num_values, int null_count, const uint8_t* valid_bits,
                          int64_t valid_bits_offset,
                          typename EncodingTraits<ByteArrayType>::Accumulator* out,
                          int* out_values_decoded) {
    // We're going to decode `num_values - null_count` PLAIN values,
    // and each value has a 4-byte length header that doesn't count for the
    // Arrow binary data length.
    int64_t estimated_data_length =
        len_ - 4 * static_cast<int64_t>(num_values - null_count);
    if (ARROW_PREDICT_FALSE(estimated_data_length < 0)) {
      return Status::Invalid("Invalid or truncated PLAIN-encoded BYTE_ARRAY data");
    }

    auto visit_binary_helper = [&](auto* helper) {
      int values_decoded = 0;

      auto visit_run = [&](int64_t position, int64_t run_length, bool is_valid) {
        if (is_valid) {
          for (int64_t i = 0; i < run_length; ++i) {
            // We ensure `len_` is sufficient thanks to:
            //   1. the initial `estimated_data_length` check above,
            //   2. the running `value_len > estimated_data_length` check below.
            // This precondition follows from those two checks.
            DCHECK_GE(len_, 4);
            auto value_len = SafeLoadAs<int32_t>(data_);
            // This check also ensures that `value_len <= len_ - 4` due to the way
            // `estimated_data_length` is computed.
            if (ARROW_PREDICT_FALSE(value_len < 0 || value_len > estimated_data_length)) {
              return Status::Invalid(
                  "Invalid or truncated PLAIN-encoded BYTE_ARRAY data");
            }
            RETURN_NOT_OK(
                helper->AppendValue(data_ + 4, value_len, estimated_data_length));
            auto increment = value_len + 4;
            data_ += increment;
            len_ -= increment;
            estimated_data_length -= value_len;
            DCHECK_GE(estimated_data_length, 0);
          }
          values_decoded += static_cast<int>(run_length);
          DCHECK_LE(values_decoded, num_values);
          return Status::OK();
        } else {
          return helper->AppendNulls(run_length);
        }
      };

      RETURN_NOT_OK(
          VisitBitRuns(valid_bits, valid_bits_offset, num_values, std::move(visit_run)));

      num_values_ -= values_decoded;
      *out_values_decoded = values_decoded;
      return Status::OK();
    };

    return DispatchArrowBinaryHelper<ByteArrayType>(
        out, num_values, estimated_data_length, visit_binary_helper);
  }

  template <typename BuilderType>
  Status DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                     int64_t valid_bits_offset, BuilderType* builder,
                     int* out_values_decoded) {
    RETURN_NOT_OK(builder->Reserve(num_values));
    int values_decoded = 0;

    RETURN_NOT_OK(VisitBitRuns(
        valid_bits, valid_bits_offset, num_values,
        [&](int64_t position, int64_t run_length, bool is_valid) {
          if (is_valid) {
            for (int64_t i = 0; i < run_length; ++i) {
              if (ARROW_PREDICT_FALSE(len_ < 4)) {
                return Status::Invalid(
                    "Invalid or truncated PLAIN-encoded BYTE_ARRAY data");
              }
              auto value_len = SafeLoadAs<int32_t>(data_);
              if (ARROW_PREDICT_FALSE(value_len < 0 || value_len > len_ - 4)) {
                return Status::Invalid(
                    "Invalid or truncated PLAIN-encoded BYTE_ARRAY data");
              }
              RETURN_NOT_OK(builder->Append(data_ + 4, value_len));
              auto increment = value_len + 4;
              data_ += increment;
              len_ -= increment;
            }
            values_decoded += static_cast<int>(run_length);
            return Status::OK();
          } else {
            return builder->AppendNulls(run_length);
          }
        }));

    num_values_ -= values_decoded;
    *out_values_decoded = values_decoded;
    return Status::OK();
  }
};

class PlainFLBADecoder : public PlainDecoder<FLBAType>, public FLBADecoder {
 public:
  using Base = PlainDecoder<FLBAType>;
  using Base::PlainDecoder;
};

// ----------------------------------------------------------------------
// Dictionary decoding

template <typename Type>
class DictDecoderImpl : public TypedDecoderImpl<Type>, public DictDecoder<Type> {
 public:
  typedef typename Type::c_type T;

  // Initializes the dictionary with values from 'dictionary'. The data in
  // dictionary is not guaranteed to persist in memory after this call so the
  // dictionary decoder needs to copy the data out if necessary.
  explicit DictDecoderImpl(const ColumnDescriptor* descr,
                           MemoryPool* pool = ::arrow::default_memory_pool())
      : TypedDecoderImpl<Type>(descr, Encoding::RLE_DICTIONARY),
        dictionary_(AllocateBuffer(pool, 0)),
        dictionary_length_(0),
        byte_array_data_(AllocateBuffer(pool, 0)),
        byte_array_offsets_(AllocateBuffer(pool, 0)),
        indices_scratch_space_(AllocateBuffer(pool, 0)) {}

  // Perform type-specific initialization
  void SetDict(TypedDecoder<Type>* dictionary) override;

  void SetData(int num_values, const uint8_t* data, int len) override {
    this->num_values_ = num_values;
    if (len == 0) {
      // Initialize dummy decoder to avoid crashes later on
      idx_decoder_ =
          ::arrow::util::RleBitPackedDecoder<int32_t>(data, len, /*bit_width=*/1);
      return;
    }
    uint8_t bit_width = *data;
    if (ARROW_PREDICT_FALSE(bit_width > 32)) {
      throw ParquetException("Invalid or corrupted bit_width " +
                             std::to_string(bit_width) + ". Maximum allowed is 32.");
    }
    idx_decoder_ = ::arrow::util::RleBitPackedDecoder<int32_t>(++data, --len, bit_width);
  }

  int Decode(T* buffer, int num_values) override {
    num_values = std::min(num_values, this->num_values_);
    int decoded_values = idx_decoder_.GetBatchWithDict(
        dictionary_->data_as<T>(), dictionary_length_, buffer, num_values);
    if (decoded_values != num_values) {
      ParquetException::EofException();
    }
    this->num_values_ -= num_values;
    return num_values;
  }

  int DecodeSpaced(T* buffer, int num_values, int null_count, const uint8_t* valid_bits,
                   int64_t valid_bits_offset) override {
    num_values = std::min(num_values, this->num_values_);
    if (num_values != idx_decoder_.GetBatchWithDictSpaced(
                          dictionary_->data_as<T>(), dictionary_length_, buffer,
                          num_values, null_count, valid_bits, valid_bits_offset)) {
      ParquetException::EofException();
    }
    this->num_values_ -= num_values;
    return num_values;
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<Type>::Accumulator* out) override;

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<Type>::DictAccumulator* out) override;

  void InsertDictionary(::arrow::ArrayBuilder* builder) override;

  int DecodeIndicesSpaced(int num_values, int null_count, const uint8_t* valid_bits,
                          int64_t valid_bits_offset,
                          ::arrow::ArrayBuilder* builder) override {
    if (num_values > 0) {
      // TODO(wesm): Refactor to batch reads for improved memory use. It is not
      // trivial because the null_count is relative to the entire bitmap
      PARQUET_THROW_NOT_OK(indices_scratch_space_->TypedResize<int32_t>(
          num_values, /*shrink_to_fit=*/false));
    }

    auto indices_buffer = indices_scratch_space_->mutable_data_as<int32_t>();

    if (num_values != idx_decoder_.GetBatchSpaced(num_values, null_count, valid_bits,
                                                  valid_bits_offset, indices_buffer)) {
      ParquetException::EofException();
    }

    // XXX(wesm): Cannot append "valid bits" directly to the builder
    std::vector<uint8_t> valid_bytes(num_values, 0);
    size_t i = 0;
    VisitNullBitmapInline(
        valid_bits, valid_bits_offset, num_values, null_count,
        [&]() { valid_bytes[i++] = 1; }, [&]() { ++i; });

    auto binary_builder = checked_cast<::arrow::BinaryDictionary32Builder*>(builder);
    PARQUET_THROW_NOT_OK(
        binary_builder->AppendIndices(indices_buffer, num_values, valid_bytes.data()));
    this->num_values_ -= num_values - null_count;
    return num_values - null_count;
  }

  int DecodeIndices(int num_values, ::arrow::ArrayBuilder* builder) override {
    num_values = std::min(num_values, this->num_values_);
    if (num_values > 0) {
      // TODO(wesm): Refactor to batch reads for improved memory use. This is
      // relatively simple here because we don't have to do any bookkeeping of
      // nulls
      PARQUET_THROW_NOT_OK(indices_scratch_space_->TypedResize<int32_t>(
          num_values, /*shrink_to_fit=*/false));
    }
    auto indices_buffer = indices_scratch_space_->mutable_data_as<int32_t>();
    if (num_values != idx_decoder_.GetBatch(indices_buffer, num_values)) {
      ParquetException::EofException();
    }
    auto binary_builder = checked_cast<::arrow::BinaryDictionary32Builder*>(builder);
    PARQUET_THROW_NOT_OK(binary_builder->AppendIndices(indices_buffer, num_values));
    this->num_values_ -= num_values;
    return num_values;
  }

  int DecodeIndices(int num_values, int32_t* indices) override {
    if (num_values != idx_decoder_.GetBatch(indices, num_values)) {
      ParquetException::EofException();
    }
    this->num_values_ -= num_values;
    return num_values;
  }

  void GetDictionary(const T** dictionary, int32_t* dictionary_length) override {
    *dictionary_length = dictionary_length_;
    *dictionary = dictionary_->mutable_data_as<T>();
  }

 protected:
  Status IndexInBounds(int32_t index) const {
    if (ARROW_PREDICT_TRUE(0 <= index && index < dictionary_length_)) {
      return Status::OK();
    }
    return Status::Invalid("Index not in dictionary bounds");
  }

  inline void DecodeDict(TypedDecoder<Type>* dictionary) {
    dictionary_length_ = static_cast<int32_t>(dictionary->values_left());
    PARQUET_THROW_NOT_OK(
        dictionary_->Resize(static_cast<int64_t>(dictionary_length_) * sizeof(T),
                            /*shrink_to_fit=*/false));
    dictionary->Decode(dictionary_->mutable_data_as<T>(), dictionary_length_);
  }

  // Only one is set.
  std::shared_ptr<ResizableBuffer> dictionary_;

  int32_t dictionary_length_;

  // Data that contains the byte array data (byte_array_dictionary_ just has the
  // pointers).
  std::shared_ptr<ResizableBuffer> byte_array_data_;

  // Arrow-style byte offsets for each dictionary value. We maintain two
  // representations of the dictionary, one as ByteArray* for non-Arrow
  // consumers and this one for Arrow consumers. Since dictionaries are
  // generally pretty small to begin with this doesn't mean too much extra
  // memory use in most cases
  std::shared_ptr<ResizableBuffer> byte_array_offsets_;

  // Reusable buffer for decoding dictionary indices to be appended to a
  // BinaryDictionary32Builder
  std::shared_ptr<ResizableBuffer> indices_scratch_space_;

  ::arrow::util::RleBitPackedDecoder<int32_t> idx_decoder_;
};

template <typename Type>
void DictDecoderImpl<Type>::SetDict(TypedDecoder<Type>* dictionary) {
  DecodeDict(dictionary);
}

template <>
void DictDecoderImpl<BooleanType>::SetDict(TypedDecoder<BooleanType>* dictionary) {
  ParquetException::NYI("Dictionary encoding is not implemented for boolean values");
}

template <>
void DictDecoderImpl<ByteArrayType>::SetDict(TypedDecoder<ByteArrayType>* dictionary) {
  DecodeDict(dictionary);

  auto* dict_values = dictionary_->mutable_data_as<ByteArray>();

  int64_t total_size = 0;
  for (int i = 0; i < dictionary_length_; ++i) {
    total_size += dict_values[i].len;
  }
  PARQUET_THROW_NOT_OK(byte_array_data_->Resize(total_size,
                                                /*shrink_to_fit=*/false));
  PARQUET_THROW_NOT_OK(byte_array_offsets_->Resize(
      (static_cast<int64_t>(dictionary_length_) + 1) * sizeof(int32_t),
      /*shrink_to_fit=*/false));

  int32_t offset = 0;
  uint8_t* bytes_data = byte_array_data_->mutable_data();
  int32_t* bytes_offsets = byte_array_offsets_->mutable_data_as<int32_t>();
  for (int i = 0; i < dictionary_length_; ++i) {
    memcpy(bytes_data + offset, dict_values[i].ptr, dict_values[i].len);
    bytes_offsets[i] = offset;
    dict_values[i].ptr = bytes_data + offset;
    offset += dict_values[i].len;
  }
  bytes_offsets[dictionary_length_] = offset;
}

template <>
inline void DictDecoderImpl<FLBAType>::SetDict(TypedDecoder<FLBAType>* dictionary) {
  DecodeDict(dictionary);

  auto* dict_values = dictionary_->mutable_data_as<FLBA>();

  int fixed_len = this->type_length_;
  int64_t total_size = static_cast<int64_t>(dictionary_length_) * fixed_len;

  PARQUET_THROW_NOT_OK(byte_array_data_->Resize(total_size,
                                                /*shrink_to_fit=*/false));
  uint8_t* bytes_data = byte_array_data_->mutable_data();
  for (int32_t i = 0, offset = 0; i < dictionary_length_; ++i, offset += fixed_len) {
    memcpy(bytes_data + offset, dict_values[i].ptr, fixed_len);
    dict_values[i].ptr = bytes_data + offset;
  }
}

template <>
inline int DictDecoderImpl<Int96Type>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<Int96Type>::Accumulator* builder) {
  ParquetException::NYI("DecodeArrow to Int96Type");
}

template <>
inline int DictDecoderImpl<Int96Type>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<Int96Type>::DictAccumulator* builder) {
  ParquetException::NYI("DecodeArrow to Int96Type");
}

template <>
inline int DictDecoderImpl<ByteArrayType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<ByteArrayType>::Accumulator* builder) {
  ParquetException::NYI("DecodeArrow implemented elsewhere");
}

template <>
inline int DictDecoderImpl<ByteArrayType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<ByteArrayType>::DictAccumulator* builder) {
  ParquetException::NYI("DecodeArrow implemented elsewhere");
}

template <typename DType>
int DictDecoderImpl<DType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<DType>::DictAccumulator* builder) {
  PARQUET_THROW_NOT_OK(builder->Reserve(num_values));

  const auto* dict_values = dictionary_->data_as<typename DType::c_type>();

  VisitNullBitmapInline(
      valid_bits, valid_bits_offset, num_values, null_count,
      [&]() {
        int32_t index;
        if (ARROW_PREDICT_FALSE(!idx_decoder_.Get(&index))) {
          throw ParquetException("");
        }
        PARQUET_THROW_NOT_OK(IndexInBounds(index));
        PARQUET_THROW_NOT_OK(builder->Append(dict_values[index]));
      },
      [&]() { PARQUET_THROW_NOT_OK(builder->AppendNull()); });

  return num_values - null_count;
}

template <>
int DictDecoderImpl<BooleanType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<BooleanType>::DictAccumulator* builder) {
  ParquetException::NYI("No dictionary encoding for BooleanType");
}

template <>
inline int DictDecoderImpl<FLBAType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<FLBAType>::Accumulator* builder) {
  if (builder->byte_width() != this->type_length_) {
    throw ParquetException("Byte width mismatch: builder was " +
                           std::to_string(builder->byte_width()) + " but decoder was " +
                           std::to_string(this->type_length_));
  }

  PARQUET_THROW_NOT_OK(builder->Reserve(num_values));

  const auto* dict_values = dictionary_->data_as<FLBA>();
  PARQUET_THROW_NOT_OK(
      VisitBitRuns(valid_bits, valid_bits_offset, num_values,
                   [&](int64_t position, int64_t run_length, bool is_valid) {
                     if (is_valid) {
                       for (int64_t i = 0; i < run_length; ++i) {
                         int32_t index;
                         if (ARROW_PREDICT_FALSE(!idx_decoder_.Get(&index))) {
                           return Status::Invalid("Dict decoding failed");
                         }
                         RETURN_NOT_OK(IndexInBounds(index));
                         builder->UnsafeAppend(dict_values[index].ptr);
                       }
                       return Status::OK();
                     } else {
                       return builder->AppendNulls(run_length);
                     }
                   }));

  return num_values - null_count;
}

template <>
int DictDecoderImpl<FLBAType>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<FLBAType>::DictAccumulator* builder) {
  auto value_type =
      checked_cast<const ::arrow::DictionaryType&>(*builder->type()).value_type();
  auto byte_width =
      checked_cast<const ::arrow::FixedSizeBinaryType&>(*value_type).byte_width();
  if (byte_width != this->type_length_) {
    throw ParquetException("Byte width mismatch: builder was " +
                           std::to_string(byte_width) + " but decoder was " +
                           std::to_string(this->type_length_));
  }

  PARQUET_THROW_NOT_OK(builder->Reserve(num_values));

  const auto* dict_values = dictionary_->data_as<FLBA>();

  VisitNullBitmapInline(
      valid_bits, valid_bits_offset, num_values, null_count,
      [&]() {
        int32_t index;
        if (ARROW_PREDICT_FALSE(!idx_decoder_.Get(&index))) {
          throw ParquetException("");
        }
        PARQUET_THROW_NOT_OK(IndexInBounds(index));
        PARQUET_THROW_NOT_OK(builder->Append(dict_values[index].ptr));
      },
      [&]() { PARQUET_THROW_NOT_OK(builder->AppendNull()); });

  return num_values - null_count;
}

template <typename Type>
int DictDecoderImpl<Type>::DecodeArrow(
    int num_values, int null_count, const uint8_t* valid_bits, int64_t valid_bits_offset,
    typename EncodingTraits<Type>::Accumulator* builder) {
  PARQUET_THROW_NOT_OK(builder->Reserve(num_values));

  using value_type = typename Type::c_type;
  const auto* dict_values = dictionary_->data_as<value_type>();

  PARQUET_THROW_NOT_OK(
      VisitBitRuns(valid_bits, valid_bits_offset, num_values,
                   [&](int64_t position, int64_t run_length, bool is_valid) {
                     if (is_valid) {
                       for (int64_t i = 0; i < run_length; ++i) {
                         int32_t index;
                         if (ARROW_PREDICT_FALSE(!idx_decoder_.Get(&index))) {
                           return Status::Invalid("Dict decoding failed");
                         }
                         RETURN_NOT_OK(IndexInBounds(index));
                         builder->UnsafeAppend(dict_values[index]);
                       }
                       return Status::OK();
                     } else {
                       return builder->AppendNulls(run_length);
                     }
                   }));

  return num_values - null_count;
}

template <typename Type>
void DictDecoderImpl<Type>::InsertDictionary(::arrow::ArrayBuilder* builder) {
  ParquetException::NYI("InsertDictionary only implemented for BYTE_ARRAY types");
}

template <>
void DictDecoderImpl<ByteArrayType>::InsertDictionary(::arrow::ArrayBuilder* builder) {
  auto binary_builder = checked_cast<::arrow::BinaryDictionary32Builder*>(builder);

  // Make a BinaryArray referencing the internal dictionary data
  auto arr = std::make_shared<::arrow::BinaryArray>(
      dictionary_length_, byte_array_offsets_, byte_array_data_);
  PARQUET_THROW_NOT_OK(binary_builder->InsertMemoValues(*arr));
}

class DictByteArrayDecoderImpl : public DictDecoderImpl<ByteArrayType> {
 public:
  using BASE = DictDecoderImpl<ByteArrayType>;
  using BASE::DictDecoderImpl;

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  ::arrow::BinaryDictionary32Builder* builder) override {
    int result = 0;
    if (null_count == 0) {
      PARQUET_THROW_NOT_OK(DecodeArrowNonNull(num_values, builder, &result));
    } else {
      PARQUET_THROW_NOT_OK(DecodeArrow(num_values, null_count, valid_bits,
                                       valid_bits_offset, builder, &result));
    }
    return result;
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<ByteArrayType>::Accumulator* out) override {
    int result = 0;
    if (null_count == 0) {
      PARQUET_THROW_NOT_OK(DecodeArrowDense(num_values, null_count,
                                            /*valid_bits=*/nullptr, valid_bits_offset,
                                            out, &result));
    } else {
      PARQUET_THROW_NOT_OK(DecodeArrowDense(num_values, null_count, valid_bits,
                                            valid_bits_offset, out, &result));
    }
    return result;
  }

 private:
  Status DecodeArrowDense(int num_values, int null_count, const uint8_t* valid_bits,
                          int64_t valid_bits_offset,
                          typename EncodingTraits<ByteArrayType>::Accumulator* out,
                          int* out_num_values) {
    constexpr int32_t kBufferSize = 1024;
    int32_t indices[kBufferSize];

    auto visit_binary_helper = [&](auto* helper) {
      const auto* dict_values = dictionary_->data_as<ByteArray>();
      const int values_to_decode = num_values - null_count;
      int values_decoded = 0;
      int num_indices = 0;
      int pos_indices = 0;

      auto visit_bit_run = [&](int64_t position, int64_t length, bool valid) {
        if (valid) {
          while (length > 0) {
            if (num_indices == pos_indices) {
              // Refill indices buffer
              const auto max_batch_size =
                  std::min<int32_t>(kBufferSize, values_to_decode - values_decoded);
              num_indices = idx_decoder_.GetBatch(indices, max_batch_size);
              if (ARROW_PREDICT_FALSE(num_indices < 1)) {
                return Status::Invalid("Invalid number of indices: ", num_indices);
              }
              pos_indices = 0;
            }
            const auto batch_size = std::min<int64_t>(num_indices - pos_indices, length);
            for (int64_t j = 0; j < batch_size; ++j) {
              const auto index = indices[pos_indices++];
              RETURN_NOT_OK(IndexInBounds(index));
              const auto& val = dict_values[index];
              RETURN_NOT_OK(helper->AppendValue(val.ptr, static_cast<int32_t>(val.len)));
            }
            values_decoded += static_cast<int32_t>(batch_size);
            length -= static_cast<int32_t>(batch_size);
          }
        } else {
          for (int64_t i = 0; i < length; ++i) {
            helper->UnsafeAppendNull();
          }
        }
        return Status::OK();
      };

      RETURN_NOT_OK(
          VisitBitRuns(valid_bits, valid_bits_offset, num_values, visit_bit_run));
      *out_num_values = values_decoded;
      return Status::OK();
    };
    // The `len_` in the ByteArrayDictDecoder is the total length of the
    // RLE/Bit-pack encoded data size, so, we cannot use `len_` to reserve
    // space for binary data.
    return DispatchArrowBinaryHelper<ByteArrayType>(
        out, num_values, /*estimated_data_length=*/{}, visit_binary_helper);
  }

  template <typename BuilderType>
  Status DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                     int64_t valid_bits_offset, BuilderType* builder,
                     int* out_num_values) {
    constexpr int32_t kBufferSize = 1024;
    int32_t indices[kBufferSize];

    RETURN_NOT_OK(builder->Reserve(num_values));
    ::arrow::internal::BitmapReader bit_reader(valid_bits, valid_bits_offset, num_values);

    const auto* dict_values = dictionary_->data_as<ByteArray>();

    int values_decoded = 0;
    int num_appended = 0;
    while (num_appended < num_values) {
      bool is_valid = bit_reader.IsSet();
      bit_reader.Next();

      if (is_valid) {
        int32_t batch_size =
            std::min<int32_t>(kBufferSize, num_values - num_appended - null_count);
        int num_indices = idx_decoder_.GetBatch(indices, batch_size);

        int i = 0;
        while (true) {
          // Consume all indices
          if (is_valid) {
            auto idx = indices[i];
            RETURN_NOT_OK(IndexInBounds(idx));
            const auto& val = dict_values[idx];
            RETURN_NOT_OK(builder->Append(val.ptr, val.len));
            ++i;
            ++values_decoded;
          } else {
            RETURN_NOT_OK(builder->AppendNull());
            --null_count;
          }
          ++num_appended;
          if (i == num_indices) {
            // Do not advance the bit_reader if we have fulfilled the decode
            // request
            break;
          }
          is_valid = bit_reader.IsSet();
          bit_reader.Next();
        }
      } else {
        RETURN_NOT_OK(builder->AppendNull());
        --null_count;
        ++num_appended;
      }
    }
    *out_num_values = values_decoded;
    return Status::OK();
  }

  template <typename BuilderType>
  Status DecodeArrowNonNull(int num_values, BuilderType* builder, int* out_num_values) {
    constexpr int32_t kBufferSize = 2048;
    int32_t indices[kBufferSize];

    RETURN_NOT_OK(builder->Reserve(num_values));

    const auto* dict_values = dictionary_->data_as<ByteArray>();

    int values_decoded = 0;
    while (values_decoded < num_values) {
      int32_t batch_size = std::min<int32_t>(kBufferSize, num_values - values_decoded);
      int num_indices = idx_decoder_.GetBatch(indices, batch_size);
      if (num_indices == 0) ParquetException::EofException();
      for (int i = 0; i < num_indices; ++i) {
        auto idx = indices[i];
        RETURN_NOT_OK(IndexInBounds(idx));
        const auto& val = dict_values[idx];
        RETURN_NOT_OK(builder->Append(val.ptr, val.len));
      }
      values_decoded += num_indices;
    }
    *out_num_values = values_decoded;
    return Status::OK();
  }
};

// ----------------------------------------------------------------------
// DELTA_BINARY_PACKED decoder

template <typename DType>
class DeltaBitPackDecoder : public TypedDecoderImpl<DType> {
 public:
  using T = typename DType::c_type;
  using UT = std::make_unsigned_t<T>;

  explicit DeltaBitPackDecoder(const ColumnDescriptor* descr,
                               MemoryPool* pool = ::arrow::default_memory_pool())
      : TypedDecoderImpl<DType>(descr, Encoding::DELTA_BINARY_PACKED), pool_(pool) {
    if (DType::type_num != Type::INT32 && DType::type_num != Type::INT64) {
      throw ParquetException("Delta bit pack encoding should only be for integer data.");
    }
  }

  void SetData(int num_values, const uint8_t* data, int len) override {
    // num_values is equal to page's num_values, including null values in this page
    this->num_values_ = num_values;
    if (decoder_ == nullptr) {
      decoder_ = std::make_shared<::arrow::bit_util::BitReader>(data, len);
    } else {
      decoder_->Reset(data, len);
    }
    InitHeader();
  }

  // Set BitReader which is already initialized by DeltaLengthByteArrayDecoder or
  // DeltaByteArrayDecoder
  void SetDecoder(int num_values, std::shared_ptr<::arrow::bit_util::BitReader> decoder) {
    this->num_values_ = num_values;
    decoder_ = std::move(decoder);
    InitHeader();
  }

  int ValidValuesCount() {
    // total_values_remaining_ in header ignores of null values
    return static_cast<int>(total_values_remaining_);
  }

  int Decode(T* buffer, int max_values) override {
    return GetInternal(buffer, max_values);
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<DType>::Accumulator* out) override {
    auto reserve = [out](int64_t num_values) {
      PARQUET_THROW_NOT_OK(out->Reserve(num_values));
    };
    auto append_values = [out](T* values, int64_t num_values) {
      PARQUET_THROW_NOT_OK(out->AppendValues(values, num_values));
    };
    return DecodeArrowInternal(num_values, null_count, valid_bits, valid_bits_offset,
                               reserve, append_values);
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<DType>::DictAccumulator* out) override {
    auto reserve = [out](int64_t num_values) {
      PARQUET_THROW_NOT_OK(out->Reserve(num_values));
    };
    auto append_values = [out](T* values, int64_t num_values) {
      for (int i = 0; i < num_values; ++i) {
        PARQUET_THROW_NOT_OK(out->Append(values[i]));
      }
    };
    return DecodeArrowInternal(num_values, null_count, valid_bits, valid_bits_offset,
                               reserve, append_values);
  }

 private:
  static constexpr int kMaxDeltaBitWidth = static_cast<int>(sizeof(T) * 8);

  template <typename ReserveFunc, typename AppendValuesFunc>
  int DecodeArrowInternal(int num_values, int null_count, const uint8_t* valid_bits,
                          int64_t valid_bits_offset, ReserveFunc&& reserve_func,
                          AppendValuesFunc&& append_values_func) {
    if (null_count != 0) {
      // TODO(ARROW-34660): implement DecodeArrow with null slots.
      ParquetException::NYI("Delta bit pack DecodeArrow with null slots");
    }
    reserve_func(num_values);
    constexpr int kBatchSize = 1024;
    std::array<T, kBatchSize> values;
    int offset = 0;
    while (offset < num_values) {
      const int batch_size = std::min(num_values - offset, kBatchSize);
      int decoded_count = GetInternal(values.data(), batch_size);
      if (decoded_count != batch_size) {
        ParquetException::EofException("Not enough values in data page");
      }
      append_values_func(values.data(), batch_size);
      offset += batch_size;
    }
    return num_values;
  }

  void InitHeader() {
    if (!decoder_->GetVlqInt(&values_per_block_) ||
        !decoder_->GetVlqInt(&mini_blocks_per_block_) ||
        !decoder_->GetVlqInt(&total_value_count_) ||
        !decoder_->GetZigZagVlqInt(&last_value_)) {
      ParquetException::EofException("InitHeader EOF");
    }

    if (values_per_block_ == 0) {
      throw ParquetException("cannot have zero value per block");
    }
    if (values_per_block_ % 128 != 0) {
      throw ParquetException(
          "the number of values in a block must be multiple of 128, but it's " +
          std::to_string(values_per_block_));
    }
    if (mini_blocks_per_block_ == 0) {
      throw ParquetException("cannot have zero miniblock per block");
    }
    values_per_mini_block_ = values_per_block_ / mini_blocks_per_block_;
    if (values_per_mini_block_ == 0) {
      throw ParquetException("cannot have zero value per miniblock");
    }
    if (values_per_mini_block_ % 32 != 0) {
      throw ParquetException(
          "the number of values in a miniblock must be multiple of 32, but it's " +
          std::to_string(values_per_mini_block_));
    }

    total_values_remaining_ = total_value_count_;
    if (delta_bit_widths_ == nullptr) {
      delta_bit_widths_ = AllocateBuffer(pool_, mini_blocks_per_block_);
    } else {
      PARQUET_THROW_NOT_OK(
          delta_bit_widths_->Resize(mini_blocks_per_block_, /*shrink_to_fit*/ false));
    }
    first_block_initialized_ = false;
    values_remaining_current_mini_block_ = 0;
  }

  void InitBlock() {
    DCHECK_GT(total_values_remaining_, 0) << "InitBlock called at EOF";

    if (!decoder_->GetZigZagVlqInt(&min_delta_))
      ParquetException::EofException("InitBlock EOF");

    // read the bitwidth of each miniblock
    uint8_t* bit_width_data = delta_bit_widths_->mutable_data();
    for (uint32_t i = 0; i < mini_blocks_per_block_; ++i) {
      if (!decoder_->GetAligned<uint8_t>(1, bit_width_data + i)) {
        ParquetException::EofException("Decode bit-width EOF");
      }
      // Note that non-conformant bitwidth entries are allowed by the Parquet spec
      // for extraneous miniblocks in the last block (GH-14923), so we check
      // the bitwidths when actually using them (see InitMiniBlock()).
    }

    mini_block_idx_ = 0;
    first_block_initialized_ = true;
    InitMiniBlock(bit_width_data[0]);
  }

  void InitMiniBlock(int bit_width) {
    if (ARROW_PREDICT_FALSE(bit_width > kMaxDeltaBitWidth)) {
      throw ParquetException("delta bit width larger than integer bit width");
    }
    delta_bit_width_ = bit_width;
    values_remaining_current_mini_block_ = values_per_mini_block_;
  }

  int GetInternal(T* buffer, int max_values) {
    max_values = static_cast<int>(std::min<int64_t>(max_values, total_values_remaining_));
    if (max_values == 0) {
      return 0;
    }

    int i = 0;

    if (ARROW_PREDICT_FALSE(!first_block_initialized_)) {
      // This is the first time we decode this data page, first output the
      // last value and initialize the first block.
      buffer[i++] = last_value_;
      if (ARROW_PREDICT_FALSE(i == max_values)) {
        // When i reaches max_values here we have two different possibilities:
        // 1. total_value_count_ == 1, which means that the page may have only
        //    one value (encoded in the header), and we should not initialize
        //    any block, nor should we skip any padding bits below.
        // 2. total_value_count_ != 1, which means we should initialize the
        //    incoming block for subsequent reads.
        if (total_value_count_ != 1) {
          InitBlock();
        }
        total_values_remaining_ -= max_values;
        this->num_values_ -= max_values;
        return max_values;
      }
      InitBlock();
    }

    DCHECK(first_block_initialized_);
    while (i < max_values) {
      // Ensure we have an initialized mini-block
      if (ARROW_PREDICT_FALSE(values_remaining_current_mini_block_ == 0)) {
        ++mini_block_idx_;
        if (mini_block_idx_ < mini_blocks_per_block_) {
          InitMiniBlock(delta_bit_widths_->data()[mini_block_idx_]);
        } else {
          InitBlock();
        }
      }

      int values_decode = std::min(values_remaining_current_mini_block_,
                                   static_cast<uint32_t>(max_values - i));
      if (delta_bit_width_ == 0) {
        // Fast path that avoids a back-to-back dependency between two consecutive
        // computations: we know all deltas decode to zero. We actually don't
        // even need to decode them.
        for (int j = 0; j < values_decode; ++j) {
          buffer[i + j] = static_cast<UT>(last_value_) +
                          static_cast<UT>(j + 1) * static_cast<UT>(min_delta_);
        }
        last_value_ += static_cast<UT>(values_decode) * static_cast<UT>(min_delta_);
      } else {
        if (decoder_->GetBatch(delta_bit_width_, buffer + i, values_decode) !=
            values_decode) {
          ParquetException::EofException();
        }
        for (int j = 0; j < values_decode; ++j) {
          // Addition between min_delta, packed int and last_value should be treated as
          // unsigned addition. Overflow is as expected.
          buffer[i + j] = static_cast<UT>(min_delta_) + static_cast<UT>(buffer[i + j]) +
                          static_cast<UT>(last_value_);
          last_value_ = buffer[i + j];
        }
      }
      values_remaining_current_mini_block_ -= values_decode;
      i += values_decode;
    }
    total_values_remaining_ -= max_values;
    this->num_values_ -= max_values;

    if (ARROW_PREDICT_FALSE(total_values_remaining_ == 0)) {
      uint32_t padding_bits = values_remaining_current_mini_block_ * delta_bit_width_;
      // skip the padding bits
      if (!decoder_->Advance(padding_bits)) {
        ParquetException::EofException();
      }
      values_remaining_current_mini_block_ = 0;
    }
    return max_values;
  }

  MemoryPool* pool_;
  std::shared_ptr<::arrow::bit_util::BitReader> decoder_;
  uint32_t values_per_block_;
  uint32_t mini_blocks_per_block_;
  uint32_t values_per_mini_block_;
  uint32_t total_value_count_;

  uint32_t total_values_remaining_;
  // Remaining values in current mini block. If the current block is the last mini block,
  // values_remaining_current_mini_block_ may greater than total_values_remaining_.
  uint32_t values_remaining_current_mini_block_;

  // If the page doesn't contain any block, `first_block_initialized_` will
  // always be false. Otherwise, it will be true when first block initialized.
  bool first_block_initialized_;
  T min_delta_;
  uint32_t mini_block_idx_;
  std::shared_ptr<ResizableBuffer> delta_bit_widths_;
  int delta_bit_width_;

  T last_value_;
};

// ----------------------------------------------------------------------
// DELTA_LENGTH_BYTE_ARRAY decoder

class DeltaLengthByteArrayDecoder : public TypedDecoderImpl<ByteArrayType> {
 public:
  using Base = TypedDecoderImpl<ByteArrayType>;

  explicit DeltaLengthByteArrayDecoder(const ColumnDescriptor* descr,
                                       MemoryPool* pool = ::arrow::default_memory_pool())
      : Base(descr, Encoding::DELTA_LENGTH_BYTE_ARRAY),
        pool_(pool),
        len_decoder_(nullptr, pool),
        buffered_length_(AllocateBuffer(pool, 0)) {}

  void SetData(int num_values, const uint8_t* data, int len) override {
    Base::SetData(num_values, data, len);
    if (decoder_ == nullptr) {
      decoder_ = std::make_shared<::arrow::bit_util::BitReader>(data, len);
    } else {
      decoder_->Reset(data, len);
    }
    DecodeLengths();
  }

  int Decode(ByteArray* buffer, int max_values) override {
    // Decode up to `max_values` strings into an internal buffer
    // and reference them into `buffer`.
    max_values = std::min(max_values, num_valid_values_);
    DCHECK_GE(max_values, 0);
    if (max_values == 0) {
      return 0;
    }

    int32_t data_size = 0;
    const int32_t* length_ptr = buffered_length_->data_as<int32_t>() + length_idx_;
    int bytes_offset = len_ - decoder_->bytes_left();
    for (int i = 0; i < max_values; ++i) {
      int32_t len = length_ptr[i];
      if (ARROW_PREDICT_FALSE(len < 0)) {
        throw ParquetException("negative string delta length");
      }
      buffer[i].len = len;
      if (AddWithOverflow(data_size, len, &data_size)) {
        throw ParquetException("excess expansion in DELTA_(LENGTH_)BYTE_ARRAY");
      }
    }
    length_idx_ += max_values;
    if (ARROW_PREDICT_FALSE(!decoder_->Advance(8 * static_cast<int64_t>(data_size)))) {
      ParquetException::EofException();
    }
    const uint8_t* data_ptr = data_ + bytes_offset;
    for (int i = 0; i < max_values; ++i) {
      buffer[i].ptr = data_ptr;
      data_ptr += buffer[i].len;
    }
    this->num_values_ -= max_values;
    num_valid_values_ -= max_values;
    return max_values;
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<ByteArrayType>::Accumulator* out) override {
    int result = 0;
    PARQUET_THROW_NOT_OK(DecodeArrowDense(num_values, null_count, valid_bits,
                                          valid_bits_offset, out, &result));
    return result;
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<ByteArrayType>::DictAccumulator* out) override {
    ParquetException::NYI(
        "DecodeArrow of DictAccumulator for DeltaLengthByteArrayDecoder");
  }

 private:
  // Decode all the encoded lengths. The decoder_ will be at the start of the encoded data
  // after that.
  void DecodeLengths() {
    len_decoder_.SetDecoder(num_values_, decoder_);

    // get the number of encoded lengths
    int num_length = len_decoder_.ValidValuesCount();
    PARQUET_THROW_NOT_OK(buffered_length_->Resize(num_length * sizeof(int32_t)));

    // call len_decoder_.Decode to decode all the lengths.
    // all the lengths are buffered in buffered_length_.
    int ret =
        len_decoder_.Decode(buffered_length_->mutable_data_as<int32_t>(), num_length);
    DCHECK_EQ(ret, num_length);
    length_idx_ = 0;
    num_valid_values_ = num_length;
  }

  Status DecodeArrowDense(int num_values, int null_count, const uint8_t* valid_bits,
                          int64_t valid_bits_offset,
                          typename EncodingTraits<ByteArrayType>::Accumulator* out,
                          int* out_num_values) {
    ARROW_ASSIGN_OR_RAISE(
        auto values_buffer,
        ::arrow::AllocateBuffer(sizeof(ByteArray) * (num_values - null_count), pool_));
    auto values_data = values_buffer->template mutable_data_as<ByteArray>();

    const int num_valid_values = Decode(values_data, num_values - null_count);
    if (ARROW_PREDICT_FALSE(num_values - null_count != num_valid_values)) {
      throw ParquetException("Expected to decode ", num_values - null_count,
                             " values, but decoded ", num_valid_values, " values.");
    }

    auto visit_binary_helper = [&](auto* helper) {
      auto values_ptr = reinterpret_cast<const ByteArray*>(values_data);
      int value_idx = 0;

      RETURN_NOT_OK(
          VisitBitRuns(valid_bits, valid_bits_offset, num_values,
                       [&](int64_t position, int64_t run_length, bool is_valid) {
                         if (is_valid) {
                           for (int64_t i = 0; i < run_length; ++i) {
                             const auto& val = values_ptr[value_idx];
                             RETURN_NOT_OK(helper->AppendValue(
                                 val.ptr, static_cast<int32_t>(val.len)));
                             ++value_idx;
                           }
                           return Status::OK();
                         } else {
                           return helper->AppendNulls(run_length);
                         }
                       }));
      *out_num_values = num_valid_values;
      return Status::OK();
    };
    return DispatchArrowBinaryHelper<ByteArrayType>(
        out, num_values, /*estimated_data_length=*/{}, visit_binary_helper);
  }

  MemoryPool* pool_;
  std::shared_ptr<::arrow::bit_util::BitReader> decoder_;
  DeltaBitPackDecoder<Int32Type> len_decoder_;
  int num_valid_values_{0};
  uint32_t length_idx_{0};
  std::shared_ptr<ResizableBuffer> buffered_length_;
};

// ----------------------------------------------------------------------
// RLE decoder for BOOLEAN

class RleBooleanDecoder : public TypedDecoderImpl<BooleanType>, public BooleanDecoder {
 public:
  explicit RleBooleanDecoder(const ColumnDescriptor* descr)
      : TypedDecoderImpl<BooleanType>(descr, Encoding::RLE) {}

  void SetData(int num_values, const uint8_t* data, int len) override {
    num_values_ = num_values;
    uint32_t num_bytes = 0;

    if (len < 4) {
      throw ParquetException("Received invalid length : " + std::to_string(len) +
                             " (corrupt data page?)");
    }
    // Load the first 4 bytes in little-endian, which indicates the length
    num_bytes = ::arrow::bit_util::FromLittleEndian(SafeLoadAs<uint32_t>(data));
    if (num_bytes < 0 || num_bytes > static_cast<uint32_t>(len - 4)) {
      throw ParquetException("Received invalid number of bytes : " +
                             std::to_string(num_bytes) + " (corrupt data page?)");
    }

    auto decoder_data = data + 4;
    if (decoder_ == nullptr) {
      decoder_ = std::make_shared<::arrow::util::RleBitPackedDecoder<bool>>(
          decoder_data, num_bytes,
          /*bit_width=*/1);
    } else {
      decoder_->Reset(decoder_data, num_bytes, /*bit_width=*/1);
    }
  }

  int Decode(bool* buffer, int max_values) override {
    max_values = std::min(max_values, num_values_);

    if (decoder_->GetBatch(buffer, max_values) != max_values) {
      ParquetException::EofException();
    }
    num_values_ -= max_values;
    return max_values;
  }

  int Decode(uint8_t* buffer, int max_values) override {
    ParquetException::NYI("Decode(uint8_t*, int) for RleBooleanDecoder");
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<BooleanType>::Accumulator* out) override {
    if (null_count == num_values) {
      PARQUET_THROW_NOT_OK(out->AppendNulls(null_count));
      return 0;
    }
    constexpr int kBatchSize = 1024;
    std::array<bool, kBatchSize> values;
    const int num_non_null_values = num_values - null_count;
    // Remaining non-null boolean values to read from decoder.
    // We decode from `decoder_` with maximum 1024 size batches.
    int num_remain_non_null_values = num_non_null_values;
    int current_index_in_batch = 0;
    int current_batch_size = 0;
    auto next_boolean_batch = [&]() {
      DCHECK_GT(num_remain_non_null_values, 0);
      DCHECK_EQ(current_index_in_batch, current_batch_size);
      current_batch_size = std::min(num_remain_non_null_values, kBatchSize);
      int decoded_count = decoder_->GetBatch(values.data(), current_batch_size);
      if (ARROW_PREDICT_FALSE(decoded_count != current_batch_size)) {
        // required values is more than values in decoder.
        ParquetException::EofException();
      }
      num_remain_non_null_values -= current_batch_size;
      current_index_in_batch = 0;
    };

    // Reserve all values including nulls first
    PARQUET_THROW_NOT_OK(out->Reserve(num_values));
    if (null_count == 0) {
      // Fast-path for not having nulls.
      do {
        next_boolean_batch();
        PARQUET_THROW_NOT_OK(
            out->AppendValues(values.begin(), values.begin() + current_batch_size));
        num_values -= current_batch_size;
        // set current_index_in_batch to current_batch_size means
        // the whole batch is totally consumed.
        current_index_in_batch = current_batch_size;
      } while (num_values > 0);
      return num_non_null_values;
    }
    auto next_value = [&]() -> bool {
      if (current_index_in_batch == current_batch_size) {
        next_boolean_batch();
        DCHECK_GT(current_batch_size, 0);
      }
      DCHECK_LT(current_index_in_batch, current_batch_size);
      bool value = values[current_index_in_batch];
      ++current_index_in_batch;
      return value;
    };
    VisitNullBitmapInline(
        valid_bits, valid_bits_offset, num_values, null_count,
        [&]() { out->UnsafeAppend(next_value()); }, [&]() { out->UnsafeAppendNull(); });
    return num_non_null_values;
  }

  int DecodeArrow(
      int num_values, int null_count, const uint8_t* valid_bits,
      int64_t valid_bits_offset,
      typename EncodingTraits<BooleanType>::DictAccumulator* builder) override {
    ParquetException::NYI("DecodeArrow for RleBooleanDecoder");
  }

 private:
  std::shared_ptr<::arrow::util::RleBitPackedDecoder<bool>> decoder_;
};

// ----------------------------------------------------------------------
// DELTA_BYTE_ARRAY decoder

template <typename DType>
class DeltaByteArrayDecoderImpl : public TypedDecoderImpl<DType> {
  using T = typename DType::c_type;

 public:
  explicit DeltaByteArrayDecoderImpl(const ColumnDescriptor* descr,
                                     MemoryPool* pool = ::arrow::default_memory_pool())
      : TypedDecoderImpl<DType>(descr, Encoding::DELTA_BYTE_ARRAY),
        pool_(pool),
        prefix_len_decoder_(nullptr, pool),
        suffix_decoder_(nullptr, pool),
        last_value_in_previous_page_(""),
        buffered_prefix_length_(AllocateBuffer(pool, 0)),
        buffered_data_(AllocateBuffer(pool, 0)) {}

  void SetData(int num_values, const uint8_t* data, int len) override {
    this->num_values_ = num_values;
    if (decoder_) {
      decoder_->Reset(data, len);
    } else {
      decoder_ = std::make_shared<::arrow::bit_util::BitReader>(data, len);
    }
    prefix_len_decoder_.SetDecoder(num_values, decoder_);

    // get the number of encoded prefix lengths
    int num_prefix = prefix_len_decoder_.ValidValuesCount();
    // call prefix_len_decoder_.Decode to decode all the prefix lengths.
    // all the prefix lengths are buffered in buffered_prefix_length_.
    PARQUET_THROW_NOT_OK(buffered_prefix_length_->Resize(num_prefix * sizeof(int32_t)));
    int ret = prefix_len_decoder_.Decode(
        buffered_prefix_length_->mutable_data_as<int32_t>(), num_prefix);
    DCHECK_EQ(ret, num_prefix);
    prefix_len_offset_ = 0;
    num_valid_values_ = num_prefix;

    int bytes_left = decoder_->bytes_left();
    // If len < bytes_left, prefix_len_decoder.Decode will throw exception.
    DCHECK_GE(len, bytes_left);
    int suffix_begins = len - bytes_left;
    // at this time, the decoder_ will be at the start of the encoded suffix data.
    suffix_decoder_.SetData(num_values, data + suffix_begins, bytes_left);

    // TODO: read corrupted files written with bug(PARQUET-246). last_value_ should be set
    // to last_value_in_previous_page_ when decoding a new page(except the first page)
    last_value_.clear();
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<DType>::Accumulator* out) override {
    int result = 0;
    PARQUET_THROW_NOT_OK(DecodeArrowDense(num_values, null_count, valid_bits,
                                          valid_bits_offset, out, &result));
    return result;
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<DType>::DictAccumulator* builder) override {
    ParquetException::NYI("DecodeArrow of DictAccumulator for DeltaByteArrayDecoder");
  }

 protected:
  template <bool is_first_run>
  static void BuildBufferInternal(const int32_t* prefix_len_ptr, int i, ByteArray* buffer,
                                  std::string_view* prefix, uint8_t** data_ptr) {
    if (ARROW_PREDICT_FALSE(static_cast<size_t>(prefix_len_ptr[i]) > prefix->length())) {
      throw ParquetException("prefix length too large in DELTA_BYTE_ARRAY");
    }
    // For now, `buffer` points to string suffixes, and the suffix decoder
    // ensures that the suffix data has sufficient lifetime.
    if (prefix_len_ptr[i] == 0) {
      // prefix is empty: buffer[i] already points to the suffix.
      *prefix = std::string_view{buffer[i]};
      return;
    }
    DCHECK_EQ(is_first_run, i == 0);
    if constexpr (!is_first_run) {
      if (buffer[i].len == 0) {
        // suffix is empty: buffer[i] can simply point to the prefix.
        // This is not possible for the first run since the prefix
        // would point to the mutable `last_value_`.
        *prefix = prefix->substr(0, prefix_len_ptr[i]);
        buffer[i] = ByteArray(*prefix);
        return;
      }
    }
    // Both prefix and suffix are non-empty, so we need to decode the string
    // into `data_ptr`.
    // 1. Copy the prefix
    memcpy(*data_ptr, prefix->data(), prefix_len_ptr[i]);
    // 2. Copy the suffix.
    memcpy(*data_ptr + prefix_len_ptr[i], buffer[i].ptr, buffer[i].len);
    // 3. Point buffer[i] to the decoded string.
    buffer[i].ptr = *data_ptr;
    buffer[i].len += prefix_len_ptr[i];
    *data_ptr += buffer[i].len;
    *prefix = std::string_view{buffer[i]};
  }

  int GetInternal(ByteArray* buffer, int max_values) {
    // Decode up to `max_values` strings into an internal buffer
    // and reference them into `buffer`.
    max_values = std::min(max_values, num_valid_values_);
    if (max_values == 0) {
      return max_values;
    }

    int suffix_read = suffix_decoder_.Decode(buffer, max_values);
    if (ARROW_PREDICT_FALSE(suffix_read != max_values)) {
      ParquetException::EofException("Read " + std::to_string(suffix_read) +
                                     ", expecting " + std::to_string(max_values) +
                                     " from suffix decoder");
    }

    int64_t data_size = 0;
    const int32_t* prefix_len_ptr =
        buffered_prefix_length_->data_as<int32_t>() + prefix_len_offset_;
    for (int i = 0; i < max_values; ++i) {
      if (prefix_len_ptr[i] == 0) {
        // We don't need to copy the suffix if the prefix length is 0.
        continue;
      }
      if (ARROW_PREDICT_FALSE(prefix_len_ptr[i] < 0)) {
        throw ParquetException("negative prefix length in DELTA_BYTE_ARRAY");
      }
      if (buffer[i].len == 0 && i != 0) {
        // We don't need to copy the prefix if the suffix length is 0
        // and this is not the first run (that is, the prefix doesn't point
        // to the mutable `last_value_`).
        continue;
      }
      if (ARROW_PREDICT_FALSE(AddWithOverflow(data_size, prefix_len_ptr[i], &data_size) ||
                              AddWithOverflow(data_size, buffer[i].len, &data_size))) {
        throw ParquetException("excess expansion in DELTA_BYTE_ARRAY");
      }
    }
    PARQUET_THROW_NOT_OK(buffered_data_->Resize(data_size));

    std::string_view prefix{last_value_};
    uint8_t* data_ptr = buffered_data_->mutable_data();
    if (max_values > 0) {
      BuildBufferInternal</*is_first_run=*/true>(prefix_len_ptr, 0, buffer, &prefix,
                                                 &data_ptr);
    }
    for (int i = 1; i < max_values; ++i) {
      BuildBufferInternal</*is_first_run=*/false>(prefix_len_ptr, i, buffer, &prefix,
                                                  &data_ptr);
    }
    DCHECK_EQ(data_ptr - buffered_data_->mutable_data(), data_size);
    prefix_len_offset_ += max_values;
    this->num_values_ -= max_values;
    num_valid_values_ -= max_values;
    last_value_ = std::string{prefix};

    if (num_valid_values_ == 0) {
      last_value_in_previous_page_ = last_value_;
    }

    if constexpr (std::is_same_v<DType, FLBAType>) {
      // Checks all values
      for (int i = 0; i < max_values; i++) {
        if (buffer[i].len != static_cast<uint32_t>(this->type_length_)) {
          throw ParquetException("FLBA type requires fixed-length ", this->type_length_,
                                 " but got ", buffer[i].len);
        }
      }
    }

    return max_values;
  }

  Status DecodeArrowDense(int num_values, int null_count, const uint8_t* valid_bits,
                          int64_t valid_bits_offset,
                          typename EncodingTraits<DType>::Accumulator* out,
                          int* out_num_values) {
    ARROW_ASSIGN_OR_RAISE(
        auto values_buffer,
        ::arrow::AllocateBuffer(sizeof(ByteArray) * (num_values - null_count), pool_));
    auto values_data = values_buffer->template mutable_data_as<ByteArray>();

    const int num_valid_values = GetInternal(values_data, num_values - null_count);
    if (ARROW_PREDICT_FALSE(num_values - null_count != num_valid_values)) {
      throw ParquetException("Expected to decode ", num_values - null_count,
                             " values, but decoded ", num_valid_values, " values.");
    }

    auto visit_binary_helper = [&](auto* helper) {
      auto values_ptr = reinterpret_cast<const ByteArray*>(values_data);
      int value_idx = 0;

      PARQUET_THROW_NOT_OK(
          VisitBitRuns(valid_bits, valid_bits_offset, num_values,
                       [&](int64_t position, int64_t run_length, bool is_valid) {
                         if (is_valid) {
                           for (int64_t i = 0; i < run_length; ++i) {
                             const auto& val = values_ptr[value_idx];
                             RETURN_NOT_OK(helper->AppendValue(
                                 val.ptr, static_cast<int32_t>(val.len)));
                             ++value_idx;
                           }
                           return Status::OK();
                         } else {
                           return helper->AppendNulls(run_length);
                         }
                       }));

      *out_num_values = num_valid_values;
      return Status::OK();
    };
    return DispatchArrowBinaryHelper<DType>(out, num_values, /*estimated_data_length=*/{},
                                            visit_binary_helper);
  }

  MemoryPool* pool_;

 private:
  std::shared_ptr<::arrow::bit_util::BitReader> decoder_;
  DeltaBitPackDecoder<Int32Type> prefix_len_decoder_;
  DeltaLengthByteArrayDecoder suffix_decoder_;
  std::string last_value_;
  // string buffer for last value in previous page
  std::string last_value_in_previous_page_;
  int num_valid_values_{0};
  uint32_t prefix_len_offset_{0};
  std::shared_ptr<ResizableBuffer> buffered_prefix_length_;
  // buffer for decoded strings, which guarantees the lifetime of the decoded strings
  // until the next call of Decode.
  std::shared_ptr<ResizableBuffer> buffered_data_;
};

class DeltaByteArrayDecoder : public DeltaByteArrayDecoderImpl<ByteArrayType> {
 public:
  using Base = DeltaByteArrayDecoderImpl<ByteArrayType>;
  using Base::DeltaByteArrayDecoderImpl;

  int Decode(ByteArray* buffer, int max_values) override {
    return GetInternal(buffer, max_values);
  }
};

class DeltaByteArrayFLBADecoder : public DeltaByteArrayDecoderImpl<FLBAType>,
                                  public FLBADecoder {
 public:
  using Base = DeltaByteArrayDecoderImpl<FLBAType>;
  using Base::DeltaByteArrayDecoderImpl;
  using Base::pool_;

  int Decode(FixedLenByteArray* buffer, int max_values) override {
    // GetInternal currently only support ByteArray.
    std::vector<ByteArray> decode_byte_array(max_values);
    const int decoded_values_size = GetInternal(decode_byte_array.data(), max_values);
    const uint32_t type_length = static_cast<uint32_t>(this->type_length_);

    for (int i = 0; i < decoded_values_size; i++) {
      if (ARROW_PREDICT_FALSE(decode_byte_array[i].len != type_length)) {
        throw ParquetException("Fixed length byte array length mismatch");
      }
      buffer[i].ptr = decode_byte_array[i].ptr;
    }
    return decoded_values_size;
  }
};

// ----------------------------------------------------------------------
// BYTE_STREAM_SPLIT decoders

template <typename DType>
class ByteStreamSplitDecoderBase : public TypedDecoderImpl<DType> {
 public:
  using Base = TypedDecoderImpl<DType>;
  using T = typename DType::c_type;

  explicit ByteStreamSplitDecoderBase(const ColumnDescriptor* descr)
      : Base(descr, Encoding::BYTE_STREAM_SPLIT) {}

  void SetData(int num_values, const uint8_t* data, int len) final {
    // Check that the data size is consistent with the number of values
    // The spec requires that the data size is a multiple of the number of values,
    // see: https://github.com/apache/parquet-format/pull/192 .
    // GH-41562: passed in `num_values` may include nulls, so we need to check and
    // adjust the number of values.
    if (static_cast<int64_t>(num_values) * this->type_length_ < len) {
      throw ParquetException(
          "Data size (" + std::to_string(len) +
          ") is too small for the number of values in in BYTE_STREAM_SPLIT (" +
          std::to_string(num_values) + ")");
    }
    if (len % this->type_length_ != 0) {
      throw ParquetException("ByteStreamSplit data size " + std::to_string(len) +
                             " not aligned with type " + TypeToString(DType::type_num) +
                             " and byte width: " + std::to_string(this->type_length_));
    }
    num_values = len / this->type_length_;
    Base::SetData(num_values, data, len);
    stride_ = this->num_values_;
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<DType>::DictAccumulator* builder) override {
    ParquetException::NYI("DecodeArrow to DictAccumulator for BYTE_STREAM_SPLIT");
  }

  int DecodeArrow(int num_values, int null_count, const uint8_t* valid_bits,
                  int64_t valid_bits_offset,
                  typename EncodingTraits<DType>::Accumulator* builder) override {
    const int values_to_decode = num_values - null_count;
    if (ARROW_PREDICT_FALSE(this->num_values_ < values_to_decode)) {
      ParquetException::EofException();
    }

    PARQUET_THROW_NOT_OK(builder->Reserve(num_values));

    // 1. Decode directly into the FixedSizeBinary data buffer, packed to the right.
    uint8_t* decode_out = reinterpret_cast<uint8_t*>(
        builder->GetMutableValue(builder->length() + null_count));
    const int num_decoded = this->DecodeRaw(decode_out, values_to_decode);
    DCHECK_EQ(num_decoded, values_to_decode);

    if (null_count == 0) {
      // No expansion required, and no need to append the bitmap
      builder->UnsafeAdvance(num_values);
      return values_to_decode;
    }

    // 2. Expand the decode values into their final positions.
    ::arrow::util::internal::SpacedExpandLeftward(
        reinterpret_cast<uint8_t*>(builder->GetMutableValue(builder->length())),
        this->type_length_, num_values, null_count, valid_bits, valid_bits_offset);
    builder->UnsafeAdvance(num_values, valid_bits, valid_bits_offset);
    return values_to_decode;
  }

 protected:
  int DecodeRaw(uint8_t* out_buffer, int max_values) {
    const int values_to_decode = std::min(this->num_values_, max_values);
    if (ARROW_PREDICT_TRUE(values_to_decode > 0)) {
      ::arrow::util::internal::ByteStreamSplitDecode(
          this->data_, this->type_length_, values_to_decode, stride_, out_buffer);
      this->data_ += values_to_decode;
      this->num_values_ -= values_to_decode;
      this->len_ -= this->type_length_ * values_to_decode;
    }
    return values_to_decode;
  }

  uint8_t* EnsureDecodeBuffer(int64_t min_values) {
    const int64_t size = this->type_length_ * min_values;
    if (!decode_buffer_ || decode_buffer_->size() < size) {
      const auto alloc_size = ::arrow::bit_util::NextPower2(size);
      PARQUET_ASSIGN_OR_THROW(decode_buffer_, ::arrow::AllocateBuffer(alloc_size));
    }
    return decode_buffer_->mutable_data();
  }

  int stride_{0};
  std::shared_ptr<Buffer> decode_buffer_;
};

// BYTE_STREAM_SPLIT decoder for FLOAT, DOUBLE, INT32, INT64

template <typename DType>
class ByteStreamSplitDecoder : public ByteStreamSplitDecoderBase<DType> {
 public:
  using Base = ByteStreamSplitDecoderBase<DType>;
  using T = typename DType::c_type;

  using Base::Base;

  int Decode(T* buffer, int max_values) override {
    return this->DecodeRaw(reinterpret_cast<uint8_t*>(buffer), max_values);
  }
};

// BYTE_STREAM_SPLIT decoder for FIXED_LEN_BYTE_ARRAY

template <>
class ByteStreamSplitDecoder<FLBAType> : public ByteStreamSplitDecoderBase<FLBAType>,
                                         public FLBADecoder {
 public:
  using Base = ByteStreamSplitDecoderBase<FLBAType>;
  using DType = FLBAType;
  using T = FixedLenByteArray;

  using Base::Base;

  int Decode(T* buffer, int max_values) override {
    // Decode into intermediate buffer.
    max_values = std::min(max_values, this->num_values_);
    uint8_t* decode_out = this->EnsureDecodeBuffer(max_values);
    const int num_decoded = this->DecodeRaw(decode_out, max_values);
    DCHECK_EQ(num_decoded, max_values);

    for (int i = 0; i < num_decoded; ++i) {
      buffer[i] =
          FixedLenByteArray(decode_out + static_cast<int64_t>(this->type_length_) * i);
    }
    return num_decoded;
  }
};

}  // namespace

// ----------------------------------------------------------------------
// Factory functions

std::unique_ptr<Decoder> MakeDecoder(Type::type type_num, Encoding::type encoding,
                                     const ColumnDescriptor* descr,
                                     ::arrow::MemoryPool* pool) {
  if (encoding == Encoding::PLAIN) {
    switch (type_num) {
      case Type::BOOLEAN:
        return std::make_unique<PlainBooleanDecoder>(descr);
      case Type::INT32:
        return std::make_unique<PlainDecoder<Int32Type>>(descr);
      case Type::INT64:
        return std::make_unique<PlainDecoder<Int64Type>>(descr);
      case Type::INT96:
        return std::make_unique<PlainDecoder<Int96Type>>(descr);
      case Type::FLOAT:
        return std::make_unique<PlainDecoder<FloatType>>(descr);
      case Type::DOUBLE:
        return std::make_unique<PlainDecoder<DoubleType>>(descr);
      case Type::BYTE_ARRAY:
        return std::make_unique<PlainByteArrayDecoder>(descr);
      case Type::FIXED_LEN_BYTE_ARRAY:
        return std::make_unique<PlainFLBADecoder>(descr);
      default:
        break;
    }
  } else if (encoding == Encoding::BYTE_STREAM_SPLIT) {
    switch (type_num) {
      case Type::INT32:
        return std::make_unique<ByteStreamSplitDecoder<Int32Type>>(descr);
      case Type::INT64:
        return std::make_unique<ByteStreamSplitDecoder<Int64Type>>(descr);
      case Type::FLOAT:
        return std::make_unique<ByteStreamSplitDecoder<FloatType>>(descr);
      case Type::DOUBLE:
        return std::make_unique<ByteStreamSplitDecoder<DoubleType>>(descr);
      case Type::FIXED_LEN_BYTE_ARRAY:
        return std::make_unique<ByteStreamSplitDecoder<FLBAType>>(descr);
      default:
        throw ParquetException(
            "BYTE_STREAM_SPLIT only supports FLOAT, DOUBLE, INT32, INT64 "
            "and FIXED_LEN_BYTE_ARRAY");
    }
  } else if (encoding == Encoding::DELTA_BINARY_PACKED) {
    switch (type_num) {
      case Type::INT32:
        return std::make_unique<DeltaBitPackDecoder<Int32Type>>(descr, pool);
      case Type::INT64:
        return std::make_unique<DeltaBitPackDecoder<Int64Type>>(descr, pool);
      default:
        throw ParquetException(
            "DELTA_BINARY_PACKED decoder only supports INT32 and INT64");
    }
  } else if (encoding == Encoding::DELTA_BYTE_ARRAY) {
    switch (type_num) {
      case Type::BYTE_ARRAY:
        return std::make_unique<DeltaByteArrayDecoder>(descr, pool);
      case Type::FIXED_LEN_BYTE_ARRAY:
        return std::make_unique<DeltaByteArrayFLBADecoder>(descr, pool);
      default:
        throw ParquetException(
            "DELTA_BYTE_ARRAY only supports BYTE_ARRAY and FIXED_LEN_BYTE_ARRAY");
    }
  } else if (encoding == Encoding::DELTA_LENGTH_BYTE_ARRAY) {
    if (type_num == Type::BYTE_ARRAY) {
      return std::make_unique<DeltaLengthByteArrayDecoder>(descr, pool);
    }
    throw ParquetException("DELTA_LENGTH_BYTE_ARRAY only supports BYTE_ARRAY");
  } else if (encoding == Encoding::RLE) {
    if (type_num == Type::BOOLEAN) {
      return std::make_unique<RleBooleanDecoder>(descr);
    }
    throw ParquetException("RLE encoding only supports BOOLEAN");
  } else {
    ParquetException::NYI("Selected encoding is not supported");
  }
  DCHECK(false) << "Should not be able to reach this code";
  return nullptr;
}

namespace detail {
std::unique_ptr<Decoder> MakeDictDecoder(Type::type type_num,
                                         const ColumnDescriptor* descr,
                                         MemoryPool* pool) {
  switch (type_num) {
    case Type::BOOLEAN:
      ParquetException::NYI("Dictionary encoding not implemented for boolean type");
    case Type::INT32:
      return std::make_unique<DictDecoderImpl<Int32Type>>(descr, pool);
    case Type::INT64:
      return std::make_unique<DictDecoderImpl<Int64Type>>(descr, pool);
    case Type::INT96:
      return std::make_unique<DictDecoderImpl<Int96Type>>(descr, pool);
    case Type::FLOAT:
      return std::make_unique<DictDecoderImpl<FloatType>>(descr, pool);
    case Type::DOUBLE:
      return std::make_unique<DictDecoderImpl<DoubleType>>(descr, pool);
    case Type::BYTE_ARRAY:
      return std::make_unique<DictByteArrayDecoderImpl>(descr, pool);
    case Type::FIXED_LEN_BYTE_ARRAY:
      return std::make_unique<DictDecoderImpl<FLBAType>>(descr, pool);
    default:
      break;
  }
  DCHECK(false) << "Should not be able to reach this code";
  return nullptr;
}

}  // namespace detail

std::vector<Encoding::type> SupportedEncodings(Type::type physical_type) {
  switch (physical_type) {
    case Type::BOOLEAN:
      return {Encoding::PLAIN, Encoding::RLE};
    case Type::INT32:
    case Type::INT64:
      return {Encoding::PLAIN, Encoding::DELTA_BINARY_PACKED,
              Encoding::BYTE_STREAM_SPLIT};
    case Type::INT96:
      return {Encoding::PLAIN};
    case Type::FLOAT:
    case Type::DOUBLE:
      return {Encoding::PLAIN, Encoding::BYTE_STREAM_SPLIT};
    case Type::FIXED_LEN_BYTE_ARRAY:
      return {Encoding::PLAIN, Encoding::BYTE_STREAM_SPLIT, Encoding::DELTA_BYTE_ARRAY};
    case Type::BYTE_ARRAY:
      return {Encoding::PLAIN, Encoding::DELTA_LENGTH_BYTE_ARRAY,
              Encoding::DELTA_BYTE_ARRAY};
    default:
      throw ParquetException("Invalid physical type");
  }
}

}  // namespace parquet
