vortex_array/arrays/extension/vtable/
mod.rs1use smallvec::smallvec;
5use vortex_error::VortexExpect;
6use vortex_error::VortexResult;
7use vortex_error::vortex_bail;
8use vortex_error::vortex_ensure_eq;
9use vortex_error::vortex_err;
10use vortex_error::vortex_panic;
11use vortex_session::VortexSession;
12use vortex_session::registry::CachedId;
13
14use crate::ArrayRef;
15use crate::EmptyArrayData;
16use crate::ExecutionCtx;
17use crate::ExecutionResult;
18use crate::array::Array;
19use crate::array::ArrayId;
20use crate::array::ArrayParts;
21use crate::array::ArrayView;
22use crate::array::VTable;
23use crate::array::ValidityVTableFromChild;
24use crate::array::with_empty_buffers;
25use crate::arrays::extension::array::SLOT_NAMES;
26use crate::arrays::extension::array::STORAGE_SLOT;
27use crate::arrays::extension::compute::rules::PARENT_RULES;
28use crate::arrays::extension::compute::rules::RULES;
29use crate::buffer::BufferHandle;
30use crate::builders::ArrayBuilder;
31use crate::builders::ExtensionBuilder;
32use crate::dtype::DType;
33use crate::serde::ArrayChildren;
34
35mod kernel;
36mod operations;
37mod validity;
38
39#[derive(Clone, Debug)]
78pub struct Extension;
79
80pub type ExtensionArray = Array<Extension>;
82
83pub(crate) fn initialize(session: &VortexSession) {
84 kernel::initialize(session);
85}
86
87impl VTable for Extension {
88 type TypedArrayData = EmptyArrayData;
89
90 type OperationsVTable = Self;
91 type ValidityVTable = ValidityVTableFromChild;
92
93 fn id(&self) -> ArrayId {
94 static ID: CachedId = CachedId::new("vortex.ext");
95 *ID
96 }
97
98 fn validate(
99 &self,
100 _data: &EmptyArrayData,
101 dtype: &DType,
102 len: usize,
103 slots: &[Option<ArrayRef>],
104 ) -> VortexResult<()> {
105 let storage = slots[STORAGE_SLOT]
106 .as_ref()
107 .vortex_expect("ExtensionArray storage slot");
108 vortex_ensure_eq!(
109 storage.len(),
110 len,
111 "ExtensionArray length {} does not match outer length {len}",
112 storage.len(),
113 );
114
115 let ext_dtype = dtype
116 .as_extension_opt()
117 .ok_or_else(|| vortex_err!("not an extension dtype"))?;
118
119 let actual_dtype = DType::Extension(ext_dtype.clone());
120 vortex_ensure_eq!(
121 &actual_dtype,
122 dtype,
123 "ExtensionArray dtype {actual_dtype} does not match outer dtype {dtype}",
124 );
125
126 Ok(())
127 }
128
129 fn nbuffers(_array: ArrayView<'_, Self>) -> usize {
130 0
131 }
132
133 fn buffer(_array: ArrayView<'_, Self>, idx: usize) -> BufferHandle {
134 vortex_panic!("ExtensionArray buffer index {idx} out of bounds")
135 }
136
137 fn buffer_name(_array: ArrayView<'_, Self>, _idx: usize) -> Option<String> {
138 None
139 }
140
141 fn with_buffers(
142 &self,
143 array: ArrayView<'_, Self>,
144 buffers: &[BufferHandle],
145 ) -> VortexResult<ArrayParts<Self>> {
146 with_empty_buffers(self, array, buffers)
147 }
148
149 fn serialize(
150 _array: ArrayView<'_, Self>,
151 _session: &VortexSession,
152 ) -> VortexResult<Option<Vec<u8>>> {
153 Ok(Some(vec![]))
154 }
155
156 fn deserialize(
157 &self,
158 dtype: &DType,
159 len: usize,
160 metadata: &[u8],
161
162 _buffers: &[BufferHandle],
163 children: &dyn ArrayChildren,
164 _session: &VortexSession,
165 ) -> VortexResult<ArrayParts<Self>> {
166 if !metadata.is_empty() {
167 vortex_bail!(
168 "ExtensionArray expects empty metadata, got {} bytes",
169 metadata.len()
170 );
171 }
172 let DType::Extension(ext_dtype) = dtype else {
173 vortex_bail!("Not an extension DType");
174 };
175 if children.len() != 1 {
176 vortex_bail!("Expected 1 child, got {}", children.len());
177 }
178 let storage = children.get(0, ext_dtype.storage_dtype(), len)?;
179 Ok(
180 ArrayParts::new(self.clone(), dtype.clone(), len, EmptyArrayData)
181 .with_slots(smallvec![Some(storage)]),
182 )
183 }
184
185 fn slot_name(_array: ArrayView<'_, Self>, idx: usize) -> String {
186 SLOT_NAMES[idx].to_string()
187 }
188
189 fn execute(array: Array<Self>, _ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
190 Ok(ExecutionResult::done(array))
191 }
192
193 fn append_to_builder(
194 array: ArrayView<'_, Self>,
195 builder: &mut dyn ArrayBuilder,
196 ctx: &mut ExecutionCtx,
197 ) -> VortexResult<()> {
198 let Some(builder) = builder.as_any_mut().downcast_mut::<ExtensionBuilder>() else {
199 vortex_bail!("append_to_builder for Extension requires an ExtensionBuilder");
200 };
201 builder.append_extension_array(&array.into_owned(), ctx)
202 }
203
204 fn reduce(array: ArrayView<'_, Self>) -> VortexResult<Option<ArrayRef>> {
205 RULES.evaluate(array)
206 }
207
208 fn reduce_parent(
209 array: ArrayView<'_, Self>,
210 parent: &ArrayRef,
211 child_idx: usize,
212 ) -> VortexResult<Option<ArrayRef>> {
213 PARENT_RULES.evaluate(array, parent, child_idx)
214 }
215}