1use std::any::Any;
5use std::fmt::Debug;
6use std::fmt::Formatter;
7use std::hash::Hasher;
8use std::sync::Arc;
9
10use vortex_buffer::ByteBuffer;
11use vortex_error::VortexExpect;
12use vortex_error::VortexResult;
13use vortex_error::vortex_ensure;
14use vortex_error::vortex_ensure_eq;
15use vortex_error::vortex_err;
16use vortex_error::vortex_panic;
17use vortex_session::registry::Id;
18
19use crate::ExecutionCtx;
20use crate::buffer::BufferHandle;
21use crate::builders::ArrayBuilder;
22use crate::canonical::CanonicalKind;
23use crate::dtype::DType;
24use crate::dtype::Nullability;
25use crate::executor::ExecutionResult;
26use crate::executor::ExecutionStep;
27use crate::scalar::Scalar;
28use crate::validity::Validity;
29
30mod erased;
31pub use erased::*;
32
33mod plugin;
34pub use plugin::*;
35mod haystack;
36pub(crate) use haystack::ArrayHaystack;
37mod probe;
38pub use probe::*;
39
40mod foreign;
41pub(crate) use foreign::*;
42
43mod typed;
44pub use typed::*;
45
46pub mod vtable;
47pub use vtable::*;
48
49mod view;
50use smallvec::SmallVec;
51pub use view::*;
52
53use crate::hash::ArrayEq;
54use crate::hash::ArrayHash;
55
56pub type ArraySlots = SmallVec<[Option<ArrayRef>; 4]>;
61
62#[derive(Clone, Copy, Debug)]
67pub struct SlotSlice<'a> {
68 slots: &'a [Option<ArrayRef>],
69 expect: &'static str,
70}
71
72impl<'a> SlotSlice<'a> {
73 pub fn new(slots: &'a [Option<ArrayRef>], expect: &'static str) -> Self {
77 Self { slots, expect }
78 }
79
80 pub fn len(&self) -> usize {
82 self.slots.len()
83 }
84
85 pub fn is_empty(&self) -> bool {
87 self.slots.is_empty()
88 }
89
90 pub fn get(&self, idx: usize) -> Option<&'a ArrayRef> {
92 self.slots
93 .get(idx)
94 .map(|slot| slot.as_ref().vortex_expect(self.expect))
95 }
96
97 pub fn iter(&self) -> impl ExactSizeIterator<Item = &'a ArrayRef> + use<'a> {
99 let expect = self.expect;
100 self.slots
101 .iter()
102 .map(move |slot| slot.as_ref().vortex_expect(expect))
103 }
104
105 pub fn to_vec(&self) -> Vec<ArrayRef> {
107 self.iter().cloned().collect()
108 }
109}
110
111impl std::ops::Index<usize> for SlotSlice<'_> {
112 type Output = ArrayRef;
113
114 fn index(&self, idx: usize) -> &Self::Output {
115 self.slots[idx].as_ref().vortex_expect(self.expect)
116 }
117}
118
119#[doc(hidden)]
124pub(crate) trait DynArrayData: 'static + private::Sealed + Send + Sync + Debug {
125 fn as_any(&self) -> &dyn Any;
127
128 fn as_any_mut(&mut self) -> &mut dyn Any;
130
131 fn canonical_kind(&self) -> Option<CanonicalKind>;
133
134 fn validity(&self, this: &ArrayRef) -> VortexResult<Validity>;
136
137 fn append_to_builder(
141 &self,
142 this: &ArrayRef,
143 builder: &mut dyn ArrayBuilder,
144 ctx: &mut ExecutionCtx,
145 ) -> VortexResult<()>;
146
147 fn buffers(&self, this: &ArrayRef) -> Vec<ByteBuffer>;
151
152 fn buffer_handles(&self, this: &ArrayRef) -> Vec<BufferHandle>;
154
155 fn buffer_names(&self, this: &ArrayRef) -> Vec<String>;
157
158 fn named_buffers(&self, this: &ArrayRef) -> Vec<(String, BufferHandle)>;
160
161 fn nbuffers(&self, this: &ArrayRef) -> usize;
163
164 fn slot_name(&self, this: &ArrayRef, idx: usize) -> String;
166
167 fn metadata_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result;
169
170 fn dyn_array_hash(&self, state: &mut dyn Hasher, accuracy: crate::EqMode);
172
173 fn dyn_array_eq(&self, other: &ArrayRef, accuracy: crate::EqMode) -> bool;
175
176 fn with_slots(&self, this: &ArrayRef, slots: ArraySlots) -> VortexResult<ArrayRef>;
178
179 fn with_buffers(&self, this: &ArrayRef, buffers: Vec<BufferHandle>) -> VortexResult<ArrayRef>;
181
182 unsafe fn with_slots_unchecked(&self, this: &ArrayRef, slots: ArraySlots) -> ArrayRef;
195
196 fn reduce(&self, this: &ArrayRef) -> VortexResult<Option<ArrayRef>>;
198
199 fn reduce_parent(
201 &self,
202 this: &ArrayRef,
203 parent: &ArrayRef,
204 child_idx: usize,
205 ) -> VortexResult<Option<ArrayRef>>;
206
207 fn execute(&self, this: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult>;
214
215 unsafe fn execute_unchecked(
227 &self,
228 this: ArrayRef,
229 ctx: &mut ExecutionCtx,
230 ) -> VortexResult<ExecutionResult>;
231
232 fn probe_scalar_once(
240 &self,
241 this: &ArrayRef,
242 index: usize,
243 ctx: &mut ExecutionCtx,
244 ) -> VortexResult<Scalar>;
245
246 fn probe_scalar_retained(
250 &self,
251 this: &ArrayRef,
252 index: usize,
253 state: &mut Option<Box<dyn Any>>,
254 ctx: &mut ExecutionCtx,
255 ) -> VortexResult<Scalar>;
256
257 fn probe_is_valid_retained(
261 &self,
262 this: &ArrayRef,
263 index: usize,
264 state: &mut Option<Box<dyn Any>>,
265 ctx: &mut ExecutionCtx,
266 ) -> VortexResult<bool>;
267}
268
269pub trait IntoArray {
271 fn into_array(self) -> ArrayRef;
273}
274
275mod private {
276 use super::*;
277
278 pub trait Sealed {}
279
280 impl<V: VTable> Sealed for ArrayData<V> {}
281}
282
283impl<V: VTable> DynArrayData for ArrayData<V> {
292 fn canonical_kind(&self) -> Option<CanonicalKind> {
293 CanonicalKind::of::<V>()
294 }
295
296 fn as_any(&self) -> &dyn Any {
297 self
298 }
299
300 fn as_any_mut(&mut self) -> &mut dyn Any {
301 self
302 }
303
304 fn validity(&self, this: &ArrayRef) -> VortexResult<Validity> {
305 if this.dtype().is_nullable() {
306 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
307 let validity = <V::ValidityVTable as ValidityVTable<V>>::validity(view)?;
308 if let Validity::Array(array) = &validity {
309 vortex_ensure_eq!(array.len(), this.len(), "Validity array length mismatch");
310 vortex_ensure!(
311 matches!(array.dtype(), DType::Bool(Nullability::NonNullable)),
312 "Validity array is not non-nullable boolean: {}",
313 this.encoding_id(),
314 );
315 }
316 Ok(validity)
317 } else {
318 Ok(Validity::NonNullable)
319 }
320 }
321
322 fn append_to_builder(
323 &self,
324 this: &ArrayRef,
325 builder: &mut dyn ArrayBuilder,
326 ctx: &mut ExecutionCtx,
327 ) -> VortexResult<()> {
328 if builder.dtype() != this.dtype() {
329 vortex_panic!(
330 "Builder dtype mismatch: expected {}, got {}",
331 this.dtype(),
332 builder.dtype(),
333 );
334 }
335 let len = builder.len();
336
337 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
338 V::append_to_builder(view, builder, ctx)?;
339
340 assert_eq!(
341 len + this.len(),
342 builder.len(),
343 "Builder length mismatch after writing array for encoding {}",
344 this.encoding_id(),
345 );
346 Ok(())
347 }
348
349 fn buffers(&self, this: &ArrayRef) -> Vec<ByteBuffer> {
350 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
351 (0..V::nbuffers(view))
352 .map(|i| V::buffer(view, i).to_host_sync())
353 .collect()
354 }
355
356 fn buffer_handles(&self, this: &ArrayRef) -> Vec<BufferHandle> {
357 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
358 (0..V::nbuffers(view)).map(|i| V::buffer(view, i)).collect()
359 }
360
361 fn buffer_names(&self, this: &ArrayRef) -> Vec<String> {
362 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
363 (0..V::nbuffers(view))
364 .filter_map(|i| V::buffer_name(view, i))
365 .collect()
366 }
367
368 fn named_buffers(&self, this: &ArrayRef) -> Vec<(String, BufferHandle)> {
369 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
370 (0..V::nbuffers(view))
371 .filter_map(|i| V::buffer_name(view, i).map(|name| (name, V::buffer(view, i))))
372 .collect()
373 }
374
375 fn nbuffers(&self, this: &ArrayRef) -> usize {
376 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
377 V::nbuffers(view)
378 }
379
380 fn slot_name(&self, this: &ArrayRef, idx: usize) -> String {
381 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
382 V::slot_name(view, idx)
383 }
384
385 fn metadata_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
386 std::fmt::Display::fmt(&self.data, f)
387 }
388
389 fn dyn_array_hash(&self, state: &mut dyn Hasher, accuracy: crate::EqMode) {
390 let mut wrapper = HasherWrapper(state);
391 self.data.array_hash(&mut wrapper, accuracy);
393 }
394
395 fn dyn_array_eq(&self, other: &ArrayRef, accuracy: crate::EqMode) -> bool {
396 other
398 .dyn_array()
399 .as_any()
400 .downcast_ref::<Self>()
401 .is_some_and(|other_inner| self.data.array_eq(&other_inner.data, accuracy))
402 }
403
404 fn with_slots(&self, this: &ArrayRef, slots: ArraySlots) -> VortexResult<ArrayRef> {
405 let stats = this.statistics().to_owned();
406 Ok(Array::<V>::try_from_parts(ArrayParts::new(
407 self.vtable.clone(),
408 this.dtype().clone(),
409 this.len(),
410 self.data.clone(),
411 slots,
412 ))?
413 .with_stats_set(stats)
414 .into_array())
415 }
416
417 fn with_buffers(&self, this: &ArrayRef, buffers: Vec<BufferHandle>) -> VortexResult<ArrayRef> {
418 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
419 let stats = this.statistics().to_owned();
420 Ok(
421 Array::<V>::try_from_parts(V::with_buffers(&self.vtable, view, &buffers)?)?
422 .with_stats_set(stats)
423 .into_array(),
424 )
425 }
426
427 unsafe fn with_slots_unchecked(&self, this: &ArrayRef, slots: ArraySlots) -> ArrayRef {
428 let parts = ArrayParts::new(
431 self.vtable.clone(),
432 this.dtype().clone(),
433 this.len(),
434 self.data.clone(),
435 slots,
436 );
437 let encoding_id = self.vtable.id();
438 let stats = this.statistics().share_existing();
439 let uninit = Arc::new_uninit();
440
441 let store = unsafe { ArrayInner::init_arc(uninit, parts, encoding_id, stats) };
443
444 ArrayRef::from_inner(store)
445 }
446
447 fn reduce(&self, this: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
448 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
449 let Some(reduced) = V::reduce(view)? else {
450 return Ok(None);
451 };
452 vortex_ensure_eq!(
453 reduced.len(),
454 this.len(),
455 "Reduced array length mismatch from {} to {}",
456 this.encoding_id(),
457 reduced.encoding_id()
458 );
459 vortex_ensure!(
461 reduced.dtype() == this.dtype()
462 || (reduced.dtype().eq_ignore_nullability(this.dtype())
463 && !reduced.dtype().is_nullable()),
464 "Reduced array dtype mismatch from {} ({}) to {} ({})",
465 this.encoding_id(),
466 this.dtype(),
467 reduced.encoding_id(),
468 reduced.dtype()
469 );
470 Ok(Some(reduced))
471 }
472
473 fn reduce_parent(
474 &self,
475 this: &ArrayRef,
476 parent: &ArrayRef,
477 child_idx: usize,
478 ) -> VortexResult<Option<ArrayRef>> {
479 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
480 let Some(reduced) = V::reduce_parent(view, parent, child_idx)? else {
481 return Ok(None);
482 };
483
484 vortex_ensure_eq!(
485 reduced.len(),
486 parent.len(),
487 "Reduced array length mismatch from {} to {}",
488 parent.encoding_id(),
489 reduced.encoding_id()
490 );
491 vortex_ensure_eq!(
492 reduced.dtype(),
493 parent.dtype(),
494 "Reduced array dtype mismatch from {} to {}",
495 parent.encoding_id(),
496 reduced.encoding_id()
497 );
498
499 Ok(Some(reduced))
500 }
501
502 fn execute(&self, this: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
503 let len = this.len();
504 let dtype = this.dtype().clone();
505 let stats = this.statistics().to_owned();
506 let result = unsafe { self.execute_unchecked(this, ctx)? };
507
508 if matches!(result.step(), ExecutionStep::Done) {
509 if cfg!(debug_assertions) {
510 vortex_ensure_eq!(
511 result.array().len(),
512 len,
513 "Result length mismatch for {:?}",
514 self.vtable
515 );
516 vortex_ensure_eq!(
517 result.array().dtype(),
518 &dtype,
519 "Executed canonical dtype mismatch for {:?}",
520 self.vtable
521 );
522 }
523
524 result.array().statistics().set_iter(stats.into_iter());
525 }
526
527 Ok(result)
528 }
529
530 unsafe fn execute_unchecked(
531 &self,
532 this: ArrayRef,
533 ctx: &mut ExecutionCtx,
534 ) -> VortexResult<ExecutionResult> {
535 let typed = Array::<V>::try_from_array_ref(this)
536 .map_err(|_| vortex_err!("Failed to downcast array for execute"))
537 .vortex_expect("Failed to downcast array for execute");
538 V::execute(typed, ctx)
539 }
540
541 fn probe_scalar_once(
542 &self,
543 this: &ArrayRef,
544 index: usize,
545 ctx: &mut ExecutionCtx,
546 ) -> VortexResult<Scalar> {
547 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
549 <V::OperationsVTable as OperationsVTable<V>>::probe_scalar(
550 &mut ProbeState::once(view),
551 index,
552 ctx,
553 )
554 }
555
556 fn probe_scalar_retained(
557 &self,
558 this: &ArrayRef,
559 index: usize,
560 state: &mut Option<Box<dyn Any>>,
561 ctx: &mut ExecutionCtx,
562 ) -> VortexResult<Scalar> {
563 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
565 let mut state = ProbeState::repeated(view, repeated_state(state)?);
566 <V::OperationsVTable as OperationsVTable<V>>::probe_scalar(&mut state, index, ctx)
567 }
568
569 fn probe_is_valid_retained(
570 &self,
571 this: &ArrayRef,
572 index: usize,
573 state: &mut Option<Box<dyn Any>>,
574 ctx: &mut ExecutionCtx,
575 ) -> VortexResult<bool> {
576 repeated_state::<EncodingProbeState<V>>(state)?.is_valid(this, index, ctx)
577 }
578}
579
580struct HasherWrapper<'a>(&'a mut dyn Hasher);
582
583impl Hasher for HasherWrapper<'_> {
584 fn finish(&self) -> u64 {
585 self.0.finish()
586 }
587
588 fn write(&mut self, bytes: &[u8]) {
589 self.0.write(bytes);
590 }
591}
592
593pub type ArrayId = Id;