use libduckdb_sys::{
duckdb_array_vector_get_child, duckdb_list_entry, duckdb_list_vector_get_child,
duckdb_list_vector_get_size, duckdb_list_vector_reserve, duckdb_list_vector_set_size,
duckdb_struct_vector_get_child, duckdb_vector, duckdb_vector_get_data, idx_t,
};
use crate::vector::{VectorReader, VectorWriter};
pub struct StructVector;
impl StructVector {
#[inline]
#[must_use]
pub unsafe fn get_child(vector: duckdb_vector, field_idx: usize) -> duckdb_vector {
unsafe { duckdb_struct_vector_get_child(vector, field_idx as idx_t) }
}
pub unsafe fn field_reader(
vector: duckdb_vector,
field_idx: usize,
row_count: usize,
) -> VectorReader {
let child = unsafe { Self::get_child(vector, field_idx) };
unsafe { VectorReader::from_vector(child, row_count) }
}
pub unsafe fn field_writer(vector: duckdb_vector, field_idx: usize) -> VectorWriter {
let child = unsafe { Self::get_child(vector, field_idx) };
unsafe { VectorWriter::from_vector(child) }
}
}
pub struct ListVector;
impl ListVector {
#[inline]
#[must_use]
pub unsafe fn get_child(vector: duckdb_vector) -> duckdb_vector {
unsafe { duckdb_list_vector_get_child(vector) }
}
#[inline]
#[must_use]
pub unsafe fn get_size(vector: duckdb_vector) -> usize {
usize::try_from(unsafe { duckdb_list_vector_get_size(vector) }).unwrap_or(0)
}
#[inline]
pub unsafe fn set_size(vector: duckdb_vector, size: usize) {
unsafe { duckdb_list_vector_set_size(vector, size as idx_t) };
}
#[inline]
pub unsafe fn reserve(vector: duckdb_vector, capacity: usize) {
unsafe { duckdb_list_vector_reserve(vector, capacity as idx_t) };
}
pub unsafe fn set_entry(vector: duckdb_vector, row_idx: usize, offset: u64, length: u64) {
let data = unsafe { duckdb_vector_get_data(vector) };
let entry_ptr = unsafe { data.cast::<duckdb_list_entry>().add(row_idx) };
unsafe {
(*entry_ptr).offset = offset;
(*entry_ptr).length = length;
}
}
#[must_use]
pub unsafe fn get_entry(vector: duckdb_vector, row_idx: usize) -> duckdb_list_entry {
let data = unsafe { duckdb_vector_get_data(vector) };
let entry_ptr = unsafe { data.cast::<duckdb_list_entry>().add(row_idx) };
unsafe { core::ptr::read_unaligned(entry_ptr) }
}
pub unsafe fn child_writer(vector: duckdb_vector) -> VectorWriter {
let child = unsafe { Self::get_child(vector) };
unsafe { VectorWriter::from_vector(child) }
}
pub unsafe fn child_reader(vector: duckdb_vector, element_count: usize) -> VectorReader {
let child = unsafe { Self::get_child(vector) };
unsafe { VectorReader::from_vector(child, element_count) }
}
}
pub struct MapVector;
impl MapVector {
#[inline]
#[must_use]
pub unsafe fn struct_child(vector: duckdb_vector) -> duckdb_vector {
unsafe { duckdb_list_vector_get_child(vector) }
}
#[inline]
#[must_use]
pub unsafe fn keys(vector: duckdb_vector) -> duckdb_vector {
let struct_vec = unsafe { Self::struct_child(vector) };
unsafe { duckdb_struct_vector_get_child(struct_vec, 0) }
}
#[inline]
#[must_use]
pub unsafe fn values(vector: duckdb_vector) -> duckdb_vector {
let struct_vec = unsafe { Self::struct_child(vector) };
unsafe { duckdb_struct_vector_get_child(struct_vec, 1) }
}
#[inline]
#[must_use]
pub unsafe fn total_entry_count(vector: duckdb_vector) -> usize {
usize::try_from(unsafe { duckdb_list_vector_get_size(vector) }).unwrap_or(0)
}
#[inline]
pub unsafe fn reserve(vector: duckdb_vector, capacity: usize) {
unsafe { duckdb_list_vector_reserve(vector, capacity as idx_t) };
}
#[inline]
pub unsafe fn set_size(vector: duckdb_vector, size: usize) {
unsafe { duckdb_list_vector_set_size(vector, size as idx_t) };
}
#[inline]
pub unsafe fn set_entry(vector: duckdb_vector, row_idx: usize, offset: u64, length: u64) {
unsafe { ListVector::set_entry(vector, row_idx, offset, length) };
}
#[must_use]
pub unsafe fn get_entry(vector: duckdb_vector, row_idx: usize) -> duckdb_list_entry {
unsafe { ListVector::get_entry(vector, row_idx) }
}
pub unsafe fn key_writer(vector: duckdb_vector) -> VectorWriter {
let keys = unsafe { Self::keys(vector) };
unsafe { VectorWriter::from_vector(keys) }
}
pub unsafe fn value_writer(vector: duckdb_vector) -> VectorWriter {
let vals = unsafe { Self::values(vector) };
unsafe { VectorWriter::from_vector(vals) }
}
pub unsafe fn key_reader(vector: duckdb_vector, element_count: usize) -> VectorReader {
let keys = unsafe { Self::keys(vector) };
unsafe { VectorReader::from_vector(keys, element_count) }
}
pub unsafe fn value_reader(vector: duckdb_vector, element_count: usize) -> VectorReader {
let vals = unsafe { Self::values(vector) };
unsafe { VectorReader::from_vector(vals, element_count) }
}
}
pub struct ArrayVector;
impl ArrayVector {
#[inline]
#[must_use]
pub unsafe fn get_child(vector: duckdb_vector) -> duckdb_vector {
unsafe { duckdb_array_vector_get_child(vector) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use libduckdb_sys::duckdb_list_entry;
#[test]
fn list_entry_layout() {
assert_eq!(
core::mem::size_of::<duckdb_list_entry>(),
16,
"duckdb_list_entry should be {{ offset: u64, length: u64 }}"
);
}
#[test]
fn set_and_get_list_entry() {
let mut data = duckdb_list_entry {
offset: 0,
length: 0,
};
let vec_ptr: duckdb_vector = std::ptr::addr_of_mut!(data).cast();
let entry_ptr = std::ptr::addr_of_mut!(data);
unsafe {
(*entry_ptr).offset = 5;
(*entry_ptr).length = 3;
}
assert_eq!(data.offset, 5);
assert_eq!(data.length, 3);
let _ = vec_ptr; }
}