use crate::value_types::vector_layout::{
element_child_size, element_child_vector, map_keys, map_total_entries, map_values, struct_field,
};
use crate::{DuckResult, DuckValueReader, duck_error};
use super::type_desc::DuckTypeDesc;
pub(super) fn child_reader_at<'a>(
reader: &'a DuckValueReader,
index: usize,
what: &str,
) -> DuckResult<&'a DuckValueReader> {
reader.child_reader.get(index).ok_or_else(|| {
duck_error(format!(
"dynamic value: no child reader for {what} at index {index}; was the reader prepared \
for this type description?"
))
})
}
pub(super) fn prepare_dynamic_reader(
reader: &mut DuckValueReader,
desc: &DuckTypeDesc,
) -> DuckResult<()> {
let row_count = reader.vector_reader.row_count();
match desc {
DuckTypeDesc::Scalar(_) | DuckTypeDesc::Decimal { .. } => Ok(()),
DuckTypeDesc::List(element) => {
let vector = element_child_vector(reader.c_duckdb_vector);
let size = element_child_size(reader.c_duckdb_vector);
let mut child = DuckValueReader::new_from_vector(vector, size);
prepare_dynamic_reader(&mut child, element)?;
reader.child_reader = vec![child];
Ok(())
}
DuckTypeDesc::Struct(fields) => {
let mut children = Vec::with_capacity(fields.len());
for (index, (_, field_desc)) in fields.iter().enumerate() {
let vector = struct_field(reader.c_duckdb_vector, index);
let mut child = DuckValueReader::new_from_vector(vector, row_count);
prepare_dynamic_reader(&mut child, field_desc)?;
children.push(child);
}
reader.child_reader = children;
Ok(())
}
DuckTypeDesc::Map(key_desc, value_desc) => {
let total = map_total_entries(reader.c_duckdb_vector);
let mut key_reader =
DuckValueReader::new_from_vector(map_keys(reader.c_duckdb_vector), total);
prepare_dynamic_reader(&mut key_reader, key_desc)?;
let mut value_reader =
DuckValueReader::new_from_vector(map_values(reader.c_duckdb_vector), total);
prepare_dynamic_reader(&mut value_reader, value_desc)?;
reader.child_reader = vec![key_reader, value_reader];
Ok(())
}
}
}