vortex_array/array/
visitor.rs1use std::fmt::Formatter;
5use std::sync::Arc;
6
7use vortex_buffer::ByteBuffer;
8use vortex_error::VortexResult;
9
10use crate::Array;
11use crate::ArrayRef;
12use crate::IntoArray;
13use crate::arrays::ConstantArray;
14use crate::buffer::BufferHandle;
15use crate::patches::Patches;
16use crate::validity::Validity;
17
18pub trait ArrayVisitor {
19 fn children(&self) -> Vec<ArrayRef>;
21
22 fn nchildren(&self) -> usize;
24
25 fn nth_child(&self, idx: usize) -> Option<ArrayRef>;
29
30 fn children_names(&self) -> Vec<String>;
32
33 fn named_children(&self) -> Vec<(String, ArrayRef)>;
35
36 fn buffers(&self) -> Vec<ByteBuffer>;
38
39 fn buffer_handles(&self) -> Vec<BufferHandle>;
41
42 fn buffer_names(&self) -> Vec<String>;
44
45 fn named_buffers(&self) -> Vec<(String, BufferHandle)>;
47
48 fn nbuffers(&self) -> usize;
50
51 fn metadata(&self) -> VortexResult<Option<Vec<u8>>>;
54
55 fn metadata_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result;
57
58 fn is_host(&self) -> bool;
62}
63
64impl ArrayVisitor for Arc<dyn Array> {
65 fn children(&self) -> Vec<ArrayRef> {
66 self.as_ref().children()
67 }
68
69 fn nchildren(&self) -> usize {
70 self.as_ref().nchildren()
71 }
72
73 fn nth_child(&self, idx: usize) -> Option<ArrayRef> {
74 self.as_ref().nth_child(idx)
75 }
76
77 fn children_names(&self) -> Vec<String> {
78 self.as_ref().children_names()
79 }
80
81 fn named_children(&self) -> Vec<(String, ArrayRef)> {
82 self.as_ref().named_children()
83 }
84
85 fn buffers(&self) -> Vec<ByteBuffer> {
86 self.as_ref().buffers()
87 }
88
89 fn buffer_handles(&self) -> Vec<BufferHandle> {
90 self.as_ref().buffer_handles()
91 }
92
93 fn buffer_names(&self) -> Vec<String> {
94 self.as_ref().buffer_names()
95 }
96
97 fn named_buffers(&self) -> Vec<(String, BufferHandle)> {
98 self.as_ref().named_buffers()
99 }
100
101 fn nbuffers(&self) -> usize {
102 self.as_ref().nbuffers()
103 }
104
105 fn metadata(&self) -> VortexResult<Option<Vec<u8>>> {
106 self.as_ref().metadata()
107 }
108
109 fn metadata_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
110 self.as_ref().metadata_fmt(f)
111 }
112
113 fn is_host(&self) -> bool {
114 self.as_ref().is_host()
115 }
116}
117
118pub trait ArrayVisitorExt: Array {
119 fn nbuffers_recursive(&self) -> usize {
121 self.children()
122 .iter()
123 .map(ArrayVisitorExt::nbuffers_recursive)
124 .sum::<usize>()
125 + self.nbuffers()
126 }
127
128 fn depth_first_traversal(&self) -> impl Iterator<Item = ArrayRef> {
130 struct ArrayChildrenIterator {
132 stack: Vec<ArrayRef>,
133 }
134
135 impl Iterator for ArrayChildrenIterator {
136 type Item = ArrayRef;
137
138 fn next(&mut self) -> Option<Self::Item> {
139 let next = self.stack.pop()?;
140 for child in next.children().into_iter().rev() {
141 self.stack.push(child);
142 }
143 Some(next)
144 }
145 }
146
147 ArrayChildrenIterator {
148 stack: vec![self.to_array()],
149 }
150 }
151}
152
153impl<A: Array + ?Sized> ArrayVisitorExt for A {}
154
155pub trait ArrayBufferVisitor {
156 fn visit_buffer_handle(&mut self, _name: &str, handle: &BufferHandle);
157}
158
159pub trait ArrayChildVisitorUnnamed {
165 fn visit_child(&mut self, array: &ArrayRef);
167
168 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 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
193pub trait ArrayChildVisitor {
194 fn visit_child(&mut self, _name: &str, _array: &ArrayRef);
196
197 fn visit_validity(&mut self, validity: &Validity, len: usize) {
199 if let Some(vlen) = validity.maybe_len() {
200 assert_eq!(vlen, len, "Validity length mismatch");
201 }
202
203 match validity {
204 Validity::NonNullable | Validity::AllValid => {}
205 Validity::AllInvalid => {
206 self.visit_child("validity", &ConstantArray::new(false, len).into_array())
213 }
214 Validity::Array(array) => {
215 self.visit_child("validity", array);
216 }
217 }
218 }
219
220 fn visit_patches(&mut self, patches: &Patches) {
222 self.visit_child("patch_indices", patches.indices());
223 self.visit_child("patch_values", patches.values());
224 if let Some(chunk_offsets) = patches.chunk_offsets() {
225 self.visit_child("patch_chunk_offsets", chunk_offsets);
226 }
227 }
228}