use std::marker::PhantomData;
use libduckdb_sys::{duckdb_array_type_array_size, duckdb_array_vector_get_child};
use crate::{
Result,
core::LogicalTypeHandle,
ffi::{
duckdb_validity_set_row_invalid, duckdb_vector, duckdb_vector_ensure_validity_writable,
duckdb_vector_get_column_type, duckdb_vector_get_validity, duckdb_vector_size,
},
};
use super::{FlatVector, try_vector_row_is_null, vector_row_is_null};
pub struct ArrayVector<'a> {
ptr: duckdb_vector,
capacity: usize,
_phantom: PhantomData<&'a ()>,
}
impl<'a> ArrayVector<'a> {
pub(crate) unsafe fn from_raw(ptr: duckdb_vector) -> Self {
unsafe { Self::from_raw_with_capacity(ptr, duckdb_vector_size() as usize) }
}
pub(crate) unsafe fn from_raw_with_capacity(ptr: duckdb_vector, capacity: usize) -> Self {
Self {
ptr,
capacity,
_phantom: PhantomData,
}
}
pub fn logical_type(&self) -> LogicalTypeHandle {
unsafe { LogicalTypeHandle::new(duckdb_vector_get_column_type(self.ptr)) }
}
pub fn get_array_size(&self) -> u64 {
let ty = self.logical_type();
unsafe { duckdb_array_type_array_size(ty.ptr) as u64 }
}
pub fn row_is_null(&self, row: u64) -> bool {
vector_row_is_null(self.ptr, row, self.capacity)
}
pub fn try_row_is_null(&self, row: u64) -> Result<bool> {
try_vector_row_is_null(self.ptr, row, self.capacity)
}
pub fn child(&self, capacity: usize) -> FlatVector<'a> {
let array_size = self.get_array_size() as usize;
assert_eq!(
capacity % array_size,
0,
"array child capacity must be a multiple of the fixed array size"
);
let child_capacity = self
.capacity
.checked_mul(array_size)
.expect("array child capacity overflows usize");
assert!(
capacity <= child_capacity,
"array child capacity {capacity} exceeds backing capacity {child_capacity}"
);
unsafe { FlatVector::with_capacity(self.child_ptr(), capacity) }
}
pub(crate) fn child_ptr(&self) -> duckdb_vector {
unsafe { duckdb_array_vector_get_child(self.ptr) }
}
pub unsafe fn set_child<T: Copy>(&self, data: &[T]) {
unsafe { self.child(data.len()).copy(data) };
}
pub fn set_null(&mut self, row: usize) {
unsafe {
duckdb_vector_ensure_validity_writable(self.ptr);
let idx = duckdb_vector_get_validity(self.ptr);
duckdb_validity_set_row_invalid(idx, row as u64);
}
}
}