Repository: apache/arrow
File: cpp/src/parquet/decoder.cc (C++)

Code before:
    --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_);
      // Ensure we'll be allocating a non-zero-sized data buffer, to avoid encountering
      // a null pointer
      constexpr int64_t kMinReserveCapacity = 64;
      RETURN_NOT_OK(
          builder_->ReserveData(std::max(required_capacity, kMinReserveCapacity)));
    }
    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())) {}


Review comment (bug):
64 here is just a not too small or not too large number, to avoid `builder_` return an NULLPTR?

Code after:
    --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.