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 probe;
36pub use probe::*;
37
38mod foreign;
39pub(crate) use foreign::*;
40
41mod typed;
42pub use typed::*;
43
44pub mod vtable;
45pub use vtable::*;
46
47mod view;
48use smallvec::SmallVec;
49pub use view::*;
50
51use crate::hash::ArrayEq;
52use crate::hash::ArrayHash;
53
54pub type ArraySlots = SmallVec<[Option<ArrayRef>; 4]>;
59
60#[derive(Clone, Copy, Debug)]
65pub struct SlotSlice<'a> {
66 slots: &'a [Option<ArrayRef>],
67 expect: &'static str,
68}
69
70impl<'a> SlotSlice<'a> {
71 pub fn new(slots: &'a [Option<ArrayRef>], expect: &'static str) -> Self {
75 Self { slots, expect }
76 }
77
78 pub fn len(&self) -> usize {
80 self.slots.len()
81 }
82
83 pub fn is_empty(&self) -> bool {
85 self.slots.is_empty()
86 }
87
88 pub fn get(&self, idx: usize) -> Option<&'a ArrayRef> {
90 self.slots
91 .get(idx)
92 .map(|slot| slot.as_ref().vortex_expect(self.expect))
93 }
94
95 pub fn iter(&self) -> impl ExactSizeIterator<Item = &'a ArrayRef> + use<'a> {
97 let expect = self.expect;
98 self.slots
99 .iter()
100 .map(move |slot| slot.as_ref().vortex_expect(expect))
101 }
102
103 pub fn to_vec(&self) -> Vec<ArrayRef> {
105 self.iter().cloned().collect()
106 }
107}
108
109impl std::ops::Index<usize> for SlotSlice<'_> {
110 type Output = ArrayRef;
111
112 fn index(&self, idx: usize) -> &Self::Output {
113 self.slots[idx].as_ref().vortex_expect(self.expect)
114 }
115}
116
117#[doc(hidden)]
122pub(crate) trait DynArrayData: 'static + private::Sealed + Send + Sync + Debug {
123 fn as_any(&self) -> &dyn Any;
125
126 fn as_any_mut(&mut self) -> &mut dyn Any;
128
129 fn canonical_kind(&self) -> Option<CanonicalKind>;
131
132 fn validity(&self, this: &ArrayRef) -> VortexResult<Validity>;
134
135 fn append_to_builder(
139 &self,
140 this: &ArrayRef,
141 builder: &mut dyn ArrayBuilder,
142 ctx: &mut ExecutionCtx,
143 ) -> VortexResult<()>;
144
145 fn buffers(&self, this: &ArrayRef) -> Vec<ByteBuffer>;
149
150 fn buffer_handles(&self, this: &ArrayRef) -> Vec<BufferHandle>;
152
153 fn buffer_names(&self, this: &ArrayRef) -> Vec<String>;
155
156 fn named_buffers(&self, this: &ArrayRef) -> Vec<(String, BufferHandle)>;
158
159 fn nbuffers(&self, this: &ArrayRef) -> usize;
161
162 fn slot_name(&self, this: &ArrayRef, idx: usize) -> String;
164
165 fn metadata_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result;
167
168 fn dyn_array_hash(&self, state: &mut dyn Hasher, accuracy: crate::EqMode);
170
171 fn dyn_array_eq(&self, other: &ArrayRef, accuracy: crate::EqMode) -> bool;
173
174 fn with_slots(&self, this: &ArrayRef, slots: ArraySlots) -> VortexResult<ArrayRef>;
176
177 fn with_buffers(&self, this: &ArrayRef, buffers: Vec<BufferHandle>) -> VortexResult<ArrayRef>;
179
180 unsafe fn with_slots_unchecked(&self, this: &ArrayRef, slots: ArraySlots) -> ArrayRef;
193
194 fn reduce(&self, this: &ArrayRef) -> VortexResult<Option<ArrayRef>>;
196
197 fn reduce_parent(
199 &self,
200 this: &ArrayRef,
201 parent: &ArrayRef,
202 child_idx: usize,
203 ) -> VortexResult<Option<ArrayRef>>;
204
205 fn execute(&self, this: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult>;
212
213 unsafe fn execute_unchecked(
225 &self,
226 this: ArrayRef,
227 ctx: &mut ExecutionCtx,
228 ) -> VortexResult<ExecutionResult>;
229
230 fn probe_scalar_once(
238 &self,
239 this: &ArrayRef,
240 index: usize,
241 ctx: &mut ExecutionCtx,
242 ) -> VortexResult<Scalar>;
243
244 fn probe_scalar_retained(
248 &self,
249 this: &ArrayRef,
250 index: usize,
251 state: &mut Option<Box<dyn Any>>,
252 ctx: &mut ExecutionCtx,
253 ) -> VortexResult<Scalar>;
254
255 fn probe_is_valid_retained(
259 &self,
260 this: &ArrayRef,
261 index: usize,
262 state: &mut Option<Box<dyn Any>>,
263 ctx: &mut ExecutionCtx,
264 ) -> VortexResult<bool>;
265}
266
267pub trait IntoArray {
269 fn into_array(self) -> ArrayRef;
271}
272
273mod private {
274 use super::*;
275
276 pub trait Sealed {}
277
278 impl<V: VTable> Sealed for ArrayData<V> {}
279}
280
281impl<V: VTable> DynArrayData for ArrayData<V> {
290 fn canonical_kind(&self) -> Option<CanonicalKind> {
291 CanonicalKind::of::<V>()
292 }
293
294 fn as_any(&self) -> &dyn Any {
295 self
296 }
297
298 fn as_any_mut(&mut self) -> &mut dyn Any {
299 self
300 }
301
302 fn validity(&self, this: &ArrayRef) -> VortexResult<Validity> {
303 if this.dtype().is_nullable() {
304 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
305 let validity = <V::ValidityVTable as ValidityVTable<V>>::validity(view)?;
306 if let Validity::Array(array) = &validity {
307 vortex_ensure_eq!(array.len(), this.len(), "Validity array length mismatch");
308 vortex_ensure!(
309 matches!(array.dtype(), DType::Bool(Nullability::NonNullable)),
310 "Validity array is not non-nullable boolean: {}",
311 this.encoding_id(),
312 );
313 }
314 Ok(validity)
315 } else {
316 Ok(Validity::NonNullable)
317 }
318 }
319
320 fn append_to_builder(
321 &self,
322 this: &ArrayRef,
323 builder: &mut dyn ArrayBuilder,
324 ctx: &mut ExecutionCtx,
325 ) -> VortexResult<()> {
326 if builder.dtype() != this.dtype() {
327 vortex_panic!(
328 "Builder dtype mismatch: expected {}, got {}",
329 this.dtype(),
330 builder.dtype(),
331 );
332 }
333 let len = builder.len();
334
335 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
336 V::append_to_builder(view, builder, ctx)?;
337
338 assert_eq!(
339 len + this.len(),
340 builder.len(),
341 "Builder length mismatch after writing array for encoding {}",
342 this.encoding_id(),
343 );
344 Ok(())
345 }
346
347 fn buffers(&self, this: &ArrayRef) -> Vec<ByteBuffer> {
348 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
349 (0..V::nbuffers(view))
350 .map(|i| V::buffer(view, i).to_host_sync())
351 .collect()
352 }
353
354 fn buffer_handles(&self, this: &ArrayRef) -> Vec<BufferHandle> {
355 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
356 (0..V::nbuffers(view)).map(|i| V::buffer(view, i)).collect()
357 }
358
359 fn buffer_names(&self, this: &ArrayRef) -> Vec<String> {
360 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
361 (0..V::nbuffers(view))
362 .filter_map(|i| V::buffer_name(view, i))
363 .collect()
364 }
365
366 fn named_buffers(&self, this: &ArrayRef) -> Vec<(String, BufferHandle)> {
367 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
368 (0..V::nbuffers(view))
369 .filter_map(|i| V::buffer_name(view, i).map(|name| (name, V::buffer(view, i))))
370 .collect()
371 }
372
373 fn nbuffers(&self, this: &ArrayRef) -> usize {
374 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
375 V::nbuffers(view)
376 }
377
378 fn slot_name(&self, this: &ArrayRef, idx: usize) -> String {
379 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
380 V::slot_name(view, idx)
381 }
382
383 fn metadata_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
384 std::fmt::Display::fmt(&self.data, f)
385 }
386
387 fn dyn_array_hash(&self, state: &mut dyn Hasher, accuracy: crate::EqMode) {
388 let mut wrapper = HasherWrapper(state);
389 self.data.array_hash(&mut wrapper, accuracy);
391 }
392
393 fn dyn_array_eq(&self, other: &ArrayRef, accuracy: crate::EqMode) -> bool {
394 other
396 .dyn_array()
397 .as_any()
398 .downcast_ref::<Self>()
399 .is_some_and(|other_inner| self.data.array_eq(&other_inner.data, accuracy))
400 }
401
402 fn with_slots(&self, this: &ArrayRef, slots: ArraySlots) -> VortexResult<ArrayRef> {
403 let stats = this.statistics().to_owned();
404 Ok(Array::<V>::try_from_parts(ArrayParts::new(
405 self.vtable.clone(),
406 this.dtype().clone(),
407 this.len(),
408 self.data.clone(),
409 slots,
410 ))?
411 .with_stats_set(stats)
412 .into_array())
413 }
414
415 fn with_buffers(&self, this: &ArrayRef, buffers: Vec<BufferHandle>) -> VortexResult<ArrayRef> {
416 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
417 let stats = this.statistics().to_owned();
418 Ok(
419 Array::<V>::try_from_parts(V::with_buffers(&self.vtable, view, &buffers)?)?
420 .with_stats_set(stats)
421 .into_array(),
422 )
423 }
424
425 unsafe fn with_slots_unchecked(&self, this: &ArrayRef, slots: ArraySlots) -> ArrayRef {
426 let parts = ArrayParts::new(
429 self.vtable.clone(),
430 this.dtype().clone(),
431 this.len(),
432 self.data.clone(),
433 slots,
434 );
435 let encoding_id = self.vtable.id();
436 let stats = this.statistics().share_existing();
437 let uninit = Arc::new_uninit();
438
439 let store = unsafe { ArrayInner::init_arc(uninit, parts, encoding_id, stats) };
441
442 ArrayRef::from_inner(store)
443 }
444
445 fn reduce(&self, this: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
446 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
447 let Some(reduced) = V::reduce(view)? else {
448 return Ok(None);
449 };
450 vortex_ensure_eq!(
451 reduced.len(),
452 this.len(),
453 "Reduced array length mismatch from {} to {}",
454 this.encoding_id(),
455 reduced.encoding_id()
456 );
457 vortex_ensure!(
459 reduced.dtype() == this.dtype()
460 || (reduced.dtype().eq_ignore_nullability(this.dtype())
461 && !reduced.dtype().is_nullable()),
462 "Reduced array dtype mismatch from {} ({}) to {} ({})",
463 this.encoding_id(),
464 this.dtype(),
465 reduced.encoding_id(),
466 reduced.dtype()
467 );
468 Ok(Some(reduced))
469 }
470
471 fn reduce_parent(
472 &self,
473 this: &ArrayRef,
474 parent: &ArrayRef,
475 child_idx: usize,
476 ) -> VortexResult<Option<ArrayRef>> {
477 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
478 let Some(reduced) = V::reduce_parent(view, parent, child_idx)? else {
479 return Ok(None);
480 };
481
482 vortex_ensure_eq!(
483 reduced.len(),
484 parent.len(),
485 "Reduced array length mismatch from {} to {}",
486 parent.encoding_id(),
487 reduced.encoding_id()
488 );
489 vortex_ensure_eq!(
490 reduced.dtype(),
491 parent.dtype(),
492 "Reduced array dtype mismatch from {} to {}",
493 parent.encoding_id(),
494 reduced.encoding_id()
495 );
496
497 Ok(Some(reduced))
498 }
499
500 fn execute(&self, this: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
501 let len = this.len();
502 let dtype = this.dtype().clone();
503 let stats = this.statistics().to_owned();
504 let result = unsafe { self.execute_unchecked(this, ctx)? };
505
506 if matches!(result.step(), ExecutionStep::Done) {
507 if cfg!(debug_assertions) {
508 vortex_ensure_eq!(
509 result.array().len(),
510 len,
511 "Result length mismatch for {:?}",
512 self.vtable
513 );
514 vortex_ensure_eq!(
515 result.array().dtype(),
516 &dtype,
517 "Executed canonical dtype mismatch for {:?}",
518 self.vtable
519 );
520 }
521
522 result.array().statistics().set_iter(stats.into_iter());
523 }
524
525 Ok(result)
526 }
527
528 unsafe fn execute_unchecked(
529 &self,
530 this: ArrayRef,
531 ctx: &mut ExecutionCtx,
532 ) -> VortexResult<ExecutionResult> {
533 let typed = Array::<V>::try_from_array_ref(this)
534 .map_err(|_| vortex_err!("Failed to downcast array for execute"))
535 .vortex_expect("Failed to downcast array for execute");
536 V::execute(typed, ctx)
537 }
538
539 fn probe_scalar_once(
540 &self,
541 this: &ArrayRef,
542 index: usize,
543 ctx: &mut ExecutionCtx,
544 ) -> VortexResult<Scalar> {
545 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
547 <V::OperationsVTable as OperationsVTable<V>>::probe_scalar(
548 &mut ProbeState::once(view),
549 index,
550 ctx,
551 )
552 }
553
554 fn probe_scalar_retained(
555 &self,
556 this: &ArrayRef,
557 index: usize,
558 state: &mut Option<Box<dyn Any>>,
559 ctx: &mut ExecutionCtx,
560 ) -> VortexResult<Scalar> {
561 let view = unsafe { ArrayView::new_unchecked(this, &self.data) };
563 let mut state = ProbeState::repeated(view, repeated_state(state)?);
564 <V::OperationsVTable as OperationsVTable<V>>::probe_scalar(&mut state, index, ctx)
565 }
566
567 fn probe_is_valid_retained(
568 &self,
569 this: &ArrayRef,
570 index: usize,
571 state: &mut Option<Box<dyn Any>>,
572 ctx: &mut ExecutionCtx,
573 ) -> VortexResult<bool> {
574 repeated_state::<EncodingProbeState<V>>(state)?.is_valid(this, index, ctx)
575 }
576}
577
578struct HasherWrapper<'a>(&'a mut dyn Hasher);
580
581impl Hasher for HasherWrapper<'_> {
582 fn finish(&self) -> u64 {
583 self.0.finish()
584 }
585
586 fn write(&mut self, bytes: &[u8]) {
587 self.0.write(bytes);
588 }
589}
590
591pub type ArrayId = Id;