use std::fmt::Formatter;
use std::sync::Arc;
use vortex_buffer::ByteBuffer;
use vortex_error::VortexResult;
use crate::Array;
use crate::ArrayRef;
use crate::IntoArray;
use crate::arrays::ConstantArray;
use crate::buffer::BufferHandle;
use crate::patches::Patches;
use crate::validity::Validity;
pub trait ArrayVisitor {
fn children(&self) -> Vec<ArrayRef>;
fn nchildren(&self) -> usize;
fn nth_child(&self, idx: usize) -> Option<ArrayRef>;
fn children_names(&self) -> Vec<String>;
fn named_children(&self) -> Vec<(String, ArrayRef)>;
fn buffers(&self) -> Vec<ByteBuffer>;
fn buffer_handles(&self) -> Vec<BufferHandle>;
fn buffer_names(&self) -> Vec<String>;
fn named_buffers(&self) -> Vec<(String, BufferHandle)>;
fn nbuffers(&self) -> usize;
fn metadata(&self) -> VortexResult<Option<Vec<u8>>>;
fn metadata_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result;
fn is_host(&self) -> bool;
}
impl ArrayVisitor for Arc<dyn Array> {
fn children(&self) -> Vec<ArrayRef> {
self.as_ref().children()
}
fn nchildren(&self) -> usize {
self.as_ref().nchildren()
}
fn nth_child(&self, idx: usize) -> Option<ArrayRef> {
self.as_ref().nth_child(idx)
}
fn children_names(&self) -> Vec<String> {
self.as_ref().children_names()
}
fn named_children(&self) -> Vec<(String, ArrayRef)> {
self.as_ref().named_children()
}
fn buffers(&self) -> Vec<ByteBuffer> {
self.as_ref().buffers()
}
fn buffer_handles(&self) -> Vec<BufferHandle> {
self.as_ref().buffer_handles()
}
fn buffer_names(&self) -> Vec<String> {
self.as_ref().buffer_names()
}
fn named_buffers(&self) -> Vec<(String, BufferHandle)> {
self.as_ref().named_buffers()
}
fn nbuffers(&self) -> usize {
self.as_ref().nbuffers()
}
fn metadata(&self) -> VortexResult<Option<Vec<u8>>> {
self.as_ref().metadata()
}
fn metadata_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.as_ref().metadata_fmt(f)
}
fn is_host(&self) -> bool {
self.as_ref().is_host()
}
}
pub trait ArrayVisitorExt: Array {
fn nbuffers_recursive(&self) -> usize {
self.children()
.iter()
.map(ArrayVisitorExt::nbuffers_recursive)
.sum::<usize>()
+ self.nbuffers()
}
fn depth_first_traversal(&self) -> impl Iterator<Item = ArrayRef> {
struct ArrayChildrenIterator {
stack: Vec<ArrayRef>,
}
impl Iterator for ArrayChildrenIterator {
type Item = ArrayRef;
fn next(&mut self) -> Option<Self::Item> {
let next = self.stack.pop()?;
for child in next.children().into_iter().rev() {
self.stack.push(child);
}
Some(next)
}
}
ArrayChildrenIterator {
stack: vec![self.to_array()],
}
}
}
impl<A: Array + ?Sized> ArrayVisitorExt for A {}
pub trait ArrayBufferVisitor {
fn visit_buffer_handle(&mut self, _name: &str, handle: &BufferHandle);
}
pub trait ArrayChildVisitorUnnamed {
fn visit_child(&mut self, array: &ArrayRef);
fn visit_validity(&mut self, validity: &Validity, len: usize) {
if let Some(vlen) = validity.maybe_len() {
assert_eq!(vlen, len, "Validity length mismatch");
}
match validity {
Validity::NonNullable | Validity::AllValid => {}
Validity::AllInvalid => self.visit_child(&ConstantArray::new(false, len).into_array()),
Validity::Array(array) => {
self.visit_child(array);
}
}
}
fn visit_patches(&mut self, patches: &Patches) {
self.visit_child(patches.indices());
self.visit_child(patches.values());
if let Some(chunk_offsets) = patches.chunk_offsets() {
self.visit_child(chunk_offsets);
}
}
}
pub trait ArrayChildVisitor {
fn visit_child(&mut self, _name: &str, _array: &ArrayRef);
fn visit_validity(&mut self, validity: &Validity, len: usize) {
if let Some(vlen) = validity.maybe_len() {
assert_eq!(vlen, len, "Validity length mismatch");
}
match validity {
Validity::NonNullable | Validity::AllValid => {}
Validity::AllInvalid => {
self.visit_child("validity", &ConstantArray::new(false, len).into_array())
}
Validity::Array(array) => {
self.visit_child("validity", array);
}
}
}
fn visit_patches(&mut self, patches: &Patches) {
self.visit_child("patch_indices", patches.indices());
self.visit_child("patch_values", patches.values());
if let Some(chunk_offsets) = patches.chunk_offsets() {
self.visit_child("patch_chunk_offsets", chunk_offsets);
}
}
}