1use std::any::type_name;
5use std::fmt::Debug;
6use std::marker::PhantomData;
7
8use vortex_error::VortexResult;
9
10use crate::ArrayRef;
11use crate::ExecutionCtx;
12use crate::matcher::Matcher;
13use crate::vtable::VTable;
14
15pub struct ParentKernelSet<V: VTable> {
16 kernels: &'static [&'static dyn DynParentKernel<V>],
17}
18
19impl<V: VTable> ParentKernelSet<V> {
20 pub const fn new(kernels: &'static [&'static dyn DynParentKernel<V>]) -> Self {
24 Self { kernels }
25 }
26
27 pub const fn lift<K: ExecuteParentKernel<V>>(
29 kernel: &'static K,
30 ) -> &'static dyn DynParentKernel<V> {
31 const {
33 assert!(
34 !(size_of::<K>() != 0),
35 "Rule must be zero-sized to be lifted"
36 );
37 }
38 unsafe { &*(kernel as *const K as *const ParentKernelAdapter<V, K>) }
39 }
40
41 pub fn execute(
43 &self,
44 child: &V::Array,
45 parent: &ArrayRef,
46 child_idx: usize,
47 ctx: &mut ExecutionCtx,
48 ) -> VortexResult<Option<ArrayRef>> {
49 for kernel in self.kernels.iter() {
50 if !kernel.matches(parent) {
51 continue;
52 }
53 if let Some(reduced) = kernel.execute_parent(child, parent, child_idx, ctx)? {
54 return Ok(Some(reduced));
55 }
56 }
57 Ok(None)
58 }
59}
60
61pub trait ExecuteParentKernel<V: VTable>: Debug + Send + Sync + 'static {
62 type Parent: Matcher;
63
64 fn execute_parent(
66 &self,
67 array: &V::Array,
68 parent: <Self::Parent as Matcher>::Match<'_>,
69 child_idx: usize,
70 ctx: &mut ExecutionCtx,
71 ) -> VortexResult<Option<ArrayRef>>;
72}
73
74pub trait DynParentKernel<V: VTable>: Send + Sync {
75 fn matches(&self, parent: &ArrayRef) -> bool;
76
77 fn execute_parent(
78 &self,
79 child: &V::Array,
80 parent: &ArrayRef,
81 child_idx: usize,
82 ctx: &mut ExecutionCtx,
83 ) -> VortexResult<Option<ArrayRef>>;
84}
85
86pub struct ParentKernelAdapter<V, K> {
87 kernel: K,
88 _phantom: PhantomData<V>,
89}
90
91impl<V: VTable, K: ExecuteParentKernel<V>> Debug for ParentKernelAdapter<V, K> {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 f.debug_struct("ParentKernelAdapter")
94 .field("parent", &type_name::<K::Parent>())
95 .field("kernel", &self.kernel)
96 .finish()
97 }
98}
99
100impl<V: VTable, K: ExecuteParentKernel<V>> DynParentKernel<V> for ParentKernelAdapter<V, K> {
101 fn matches(&self, parent: &ArrayRef) -> bool {
102 K::Parent::matches(parent)
103 }
104
105 fn execute_parent(
106 &self,
107 child: &V::Array,
108 parent: &ArrayRef,
109 child_idx: usize,
110 ctx: &mut ExecutionCtx,
111 ) -> VortexResult<Option<ArrayRef>> {
112 let Some(parent_view) = K::Parent::try_match(parent) else {
113 return Ok(None);
114 };
115 self.kernel
116 .execute_parent(child, parent_view, child_idx, ctx)
117 }
118}