in src/parquet/arrow/writer.cc [110:180]
Status GenerateLevels(const Array& array, const std::shared_ptr<Field>& field,
int64_t* values_offset, int64_t* num_values, int64_t* num_levels,
const std::shared_ptr<ResizableBuffer>& def_levels_scratch,
std::shared_ptr<Buffer>* def_levels_out,
std::shared_ptr<Buffer>* rep_levels_out,
std::shared_ptr<Array>* values_array) {
// Work downwards to extract bitmaps and offsets
min_offset_idx_ = 0;
max_offset_idx_ = array.length();
RETURN_NOT_OK(VisitInline(array));
*num_values = max_offset_idx_ - min_offset_idx_;
*values_offset = min_offset_idx_;
*values_array = values_array_;
// Walk downwards to extract nullability
std::shared_ptr<Field> current_field = field;
nullable_.push_back(current_field->nullable());
while (current_field->type()->num_children() > 0) {
if (current_field->type()->num_children() > 1) {
return Status::NotImplemented(
"Fields with more than one child are not supported.");
} else {
current_field = current_field->type()->child(0);
}
nullable_.push_back(current_field->nullable());
}
// Generate the levels.
if (nullable_.size() == 1) {
// We have a PrimitiveArray
*rep_levels_out = nullptr;
if (nullable_[0]) {
RETURN_NOT_OK(
def_levels_scratch->Resize(array.length() * sizeof(int16_t), false));
auto def_levels_ptr =
reinterpret_cast<int16_t*>(def_levels_scratch->mutable_data());
if (array.null_count() == 0) {
std::fill(def_levels_ptr, def_levels_ptr + array.length(), 1);
} else if (array.null_count() == array.length()) {
std::fill(def_levels_ptr, def_levels_ptr + array.length(), 0);
} else {
::arrow::internal::BitmapReader valid_bits_reader(
array.null_bitmap_data(), array.offset(), array.length());
for (int i = 0; i < array.length(); i++) {
def_levels_ptr[i] = valid_bits_reader.IsSet() ? 1 : 0;
valid_bits_reader.Next();
}
}
*def_levels_out = def_levels_scratch;
} else {
*def_levels_out = nullptr;
}
*num_levels = array.length();
} else {
RETURN_NOT_OK(rep_levels_.Append(0));
RETURN_NOT_OK(HandleListEntries(0, 0, 0, array.length()));
std::shared_ptr<Array> def_levels_array;
std::shared_ptr<Array> rep_levels_array;
RETURN_NOT_OK(def_levels_.Finish(&def_levels_array));
RETURN_NOT_OK(rep_levels_.Finish(&rep_levels_array));
*def_levels_out = static_cast<PrimitiveArray*>(def_levels_array.get())->values();
*rep_levels_out = static_cast<PrimitiveArray*>(rep_levels_array.get())->values();
*num_levels = rep_levels_array->length();
}
return Status::OK();
}