Skip to content

Commit 531a071

Browse files
committed
Visit children in an unnamed way
Signed-off-by: Adam Gutglick <adam@spiraldb.com>
1 parent e6ffa76 commit 531a071

6 files changed

Lines changed: 90 additions & 9 deletions

File tree

vortex-array/src/array/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -633,16 +633,16 @@ impl<V: VTable> ArrayVisitor for ArrayAdapter<V> {
633633
children: Vec<ArrayRef>,
634634
}
635635

636-
impl ArrayChildVisitor for ChildrenCollector {
637-
fn visit_child(&mut self, _name: &str, array: &ArrayRef) {
636+
impl ArrayChildVisitorUnnamed for ChildrenCollector {
637+
fn visit_child(&mut self, array: &ArrayRef) {
638638
self.children.push(array.clone());
639639
}
640640
}
641641

642642
let mut collector = ChildrenCollector {
643643
children: Vec::new(),
644644
};
645-
<V::VisitorVTable as VisitorVTable<V>>::visit_children(&self.0, &mut collector);
645+
<V::VisitorVTable as VisitorVTable<V>>::visit_children_unnamed(&self.0, &mut collector);
646646
collector.children
647647
}
648648

vortex-array/src/array/visitor.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,40 @@ pub trait ArrayBufferVisitor {
156156
fn visit_buffer_handle(&mut self, _name: &str, handle: &BufferHandle);
157157
}
158158

159+
/// A visitor for array children that does not require names.
160+
///
161+
/// This is more efficient than [`ArrayChildVisitor`] when you only need to
162+
/// iterate over children without accessing their names (e.g., for counting
163+
/// or accessing by index).
164+
pub trait ArrayChildVisitorUnnamed {
165+
/// Visit a child of this array.
166+
fn visit_child(&mut self, array: &ArrayRef);
167+
168+
/// Utility for visiting Array validity.
169+
fn visit_validity(&mut self, validity: &Validity, len: usize) {
170+
if let Some(vlen) = validity.maybe_len() {
171+
assert_eq!(vlen, len, "Validity length mismatch");
172+
}
173+
174+
match validity {
175+
Validity::NonNullable | Validity::AllValid => {}
176+
Validity::AllInvalid => self.visit_child(&ConstantArray::new(false, len).into_array()),
177+
Validity::Array(array) => {
178+
self.visit_child(array);
179+
}
180+
}
181+
}
182+
183+
/// Utility for visiting Array patches.
184+
fn visit_patches(&mut self, patches: &Patches) {
185+
self.visit_child(patches.indices());
186+
self.visit_child(patches.values());
187+
if let Some(chunk_offsets) = patches.chunk_offsets() {
188+
self.visit_child(chunk_offsets);
189+
}
190+
}
191+
}
192+
159193
pub trait ArrayChildVisitor {
160194
/// Visit a child of this array.
161195
fn visit_child(&mut self, _name: &str, _array: &ArrayRef);

vortex-array/src/arrays/chunked/vtable/visitor.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use crate::ArrayBufferVisitor;
55
use crate::ArrayChildVisitor;
6+
use crate::ArrayChildVisitorUnnamed;
67
use crate::arrays::ChunkedArray;
78
use crate::arrays::ChunkedVTable;
89
use crate::vtable::VisitorVTable;
@@ -17,4 +18,12 @@ impl VisitorVTable<ChunkedVTable> for ChunkedVTable {
1718
visitor.visit_child(format!("chunks[{idx}]").as_str(), chunk);
1819
}
1920
}
21+
22+
fn visit_children_unnamed(array: &ChunkedArray, visitor: &mut dyn ArrayChildVisitorUnnamed) {
23+
visitor.visit_child(&array.chunk_offsets.to_array());
24+
25+
for chunk in array.chunks().iter() {
26+
visitor.visit_child(chunk);
27+
}
28+
}
2029
}

vortex-array/src/arrays/scalar_fn/vtable/visitor.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use crate::ArrayBufferVisitor;
55
use crate::ArrayChildVisitor;
6+
use crate::ArrayChildVisitorUnnamed;
67
use crate::ArrayRef;
78
use crate::arrays::scalar_fn::array::ScalarFnArray;
89
use crate::arrays::scalar_fn::vtable::ScalarFnVTable;
@@ -18,6 +19,16 @@ impl VisitorVTable<ScalarFnVTable> for ScalarFnVTable {
1819
}
1920
}
2021

22+
fn visit_children_unnamed(array: &ScalarFnArray, visitor: &mut dyn ArrayChildVisitorUnnamed) {
23+
for child in array.children.iter() {
24+
visitor.visit_child(child);
25+
}
26+
}
27+
28+
fn nchildren(array: &ScalarFnArray) -> usize {
29+
array.children.len()
30+
}
31+
2132
fn nth_child(array: &ScalarFnArray, idx: usize) -> Option<ArrayRef> {
2233
array.children.get(idx).cloned()
2334
}

vortex-array/src/arrays/struct_/vtable/visitor.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use itertools::Itertools;
55

66
use crate::ArrayBufferVisitor;
77
use crate::ArrayChildVisitor;
8+
use crate::ArrayChildVisitorUnnamed;
89
use crate::arrays::struct_::StructArray;
910
use crate::arrays::struct_::StructVTable;
1011
use crate::vtable::ValidityHelper;
@@ -19,4 +20,11 @@ impl VisitorVTable<StructVTable> for StructVTable {
1920
visitor.visit_child(name.as_ref(), field);
2021
}
2122
}
23+
24+
fn visit_children_unnamed(array: &StructArray, visitor: &mut dyn ArrayChildVisitorUnnamed) {
25+
visitor.visit_validity(array.validity(), array.len());
26+
for field in array.unmasked_fields().iter() {
27+
visitor.visit_child(field);
28+
}
29+
}
2230
}

vortex-array/src/vtable/visitor.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use crate::ArrayBufferVisitor;
55
use crate::ArrayChildVisitor;
6+
use crate::ArrayChildVisitorUnnamed;
67
use crate::ArrayRef;
78
use crate::buffer::BufferHandle;
89
use crate::vtable::VTable;
@@ -44,18 +45,36 @@ pub trait VisitorVTable<V: VTable> {
4445
/// Visit the children of the array.
4546
fn visit_children(array: &V::Array, visitor: &mut dyn ArrayChildVisitor);
4647

48+
/// Visit the children of the array without names.
49+
///
50+
/// This is more efficient than [`visit_children`] when you don't need the
51+
/// child names (e.g., for counting or accessing by index). The default
52+
/// implementation wraps the named visitor, but array types can override
53+
/// this to avoid allocating names.
54+
fn visit_children_unnamed(array: &V::Array, visitor: &mut dyn ArrayChildVisitorUnnamed) {
55+
struct UnnamedWrapper<'a>(&'a mut dyn ArrayChildVisitorUnnamed);
56+
57+
impl ArrayChildVisitor for UnnamedWrapper<'_> {
58+
fn visit_child(&mut self, _name: &str, array: &ArrayRef) {
59+
self.0.visit_child(array);
60+
}
61+
}
62+
63+
<V::VisitorVTable as VisitorVTable<V>>::visit_children(array, &mut UnnamedWrapper(visitor));
64+
}
65+
4766
/// Count the number of children in the array.
4867
fn nchildren(array: &V::Array) -> usize {
4968
struct NChildren(usize);
5069

51-
impl ArrayChildVisitor for NChildren {
52-
fn visit_child(&mut self, _name: &str, _array: &ArrayRef) {
70+
impl ArrayChildVisitorUnnamed for NChildren {
71+
fn visit_child(&mut self, _array: &ArrayRef) {
5372
self.0 += 1;
5473
}
5574
}
5675

5776
let mut visitor = NChildren(0);
58-
<V::VisitorVTable as VisitorVTable<V>>::visit_children(array, &mut visitor);
77+
<V::VisitorVTable as VisitorVTable<V>>::visit_children_unnamed(array, &mut visitor);
5978
visitor.0
6079
}
6180

@@ -69,8 +88,8 @@ pub trait VisitorVTable<V: VTable> {
6988
result: Option<ArrayRef>,
7089
}
7190

72-
impl ArrayChildVisitor for NthChildVisitor {
73-
fn visit_child(&mut self, _name: &str, array: &ArrayRef) {
91+
impl ArrayChildVisitorUnnamed for NthChildVisitor {
92+
fn visit_child(&mut self, array: &ArrayRef) {
7493
if self.current_idx == self.target_idx && self.result.is_none() {
7594
self.result = Some(array.clone());
7695
}
@@ -83,7 +102,7 @@ pub trait VisitorVTable<V: VTable> {
83102
current_idx: 0,
84103
result: None,
85104
};
86-
<V::VisitorVTable as VisitorVTable<V>>::visit_children(array, &mut visitor);
105+
<V::VisitorVTable as VisitorVTable<V>>::visit_children_unnamed(array, &mut visitor);
87106
visitor.result
88107
}
89108
}

0 commit comments

Comments
 (0)