vortex_array/vtable/
dyn_.rs1use std::any::Any;
5use std::fmt::Debug;
6use std::fmt::Display;
7use std::fmt::Formatter;
8use std::mem::transmute;
9use std::sync::Arc;
10
11use arcref::ArcRef;
12use vortex_buffer::BufferHandle;
13use vortex_dtype::DType;
14use vortex_error::VortexExpect;
15use vortex_error::VortexResult;
16use vortex_error::vortex_bail;
17use vortex_error::vortex_err;
18
19use crate::Array;
20use crate::ArrayRef;
21use crate::Canonical;
22use crate::IntoArray;
23use crate::serde::ArrayChildren;
24use crate::vtable::EncodeVTable;
25use crate::vtable::VTable;
26
27pub type ArrayId = ArcRef<str>;
29pub type ArrayVTable = ArcRef<dyn DynVTable>;
30
31pub trait DynVTable: 'static + private::Sealed + Send + Sync + Debug {
33 fn as_any(&self) -> &dyn Any;
35
36 fn id(&self) -> ArrayId;
38
39 fn build(
41 &self,
42 dtype: &DType,
43 len: usize,
44 metadata: &[u8],
45 buffers: &[BufferHandle],
46 children: &dyn ArrayChildren,
47 ) -> VortexResult<ArrayRef>;
48
49 fn with_children(
50 &self,
51 array: &dyn Array,
52 children: &dyn ArrayChildren,
53 ) -> VortexResult<ArrayRef>;
54
55 fn encode(&self, input: &Canonical, like: Option<&dyn Array>)
61 -> VortexResult<Option<ArrayRef>>;
62}
63
64#[repr(transparent)]
71pub struct ArrayVTableAdapter<V: VTable>(V);
72
73impl<V: VTable> DynVTable for ArrayVTableAdapter<V> {
74 fn as_any(&self) -> &dyn Any {
75 self
76 }
77
78 fn id(&self) -> ArrayId {
79 V::id(&self.0)
80 }
81
82 fn build(
83 &self,
84 dtype: &DType,
85 len: usize,
86 metadata_bytes: &[u8],
87 buffers: &[BufferHandle],
88 children: &dyn ArrayChildren,
89 ) -> VortexResult<ArrayRef> {
90 let metadata = V::deserialize(metadata_bytes)?;
91 let array = V::build(&self.0, dtype, len, &metadata, buffers, children)?;
92 assert_eq!(array.len(), len, "Array length mismatch after building");
93 assert_eq!(array.dtype(), dtype, "Array dtype mismatch after building");
94 Ok(array.to_array())
95 }
96
97 fn with_children(
98 &self,
99 array: &dyn Array,
100 children: &dyn ArrayChildren,
101 ) -> VortexResult<ArrayRef> {
102 let buffers: Vec<BufferHandle> = array
103 .buffers()
104 .into_iter()
105 .map(BufferHandle::Buffer)
106 .collect();
107 V::build(
108 &self.0,
109 array.dtype(),
110 array.len(),
111 &V::metadata(array.as_::<V>())?,
112 &buffers,
113 children,
114 )
115 .map(|a| a.into_array())
116 }
117
118 fn encode(
119 &self,
120 input: &Canonical,
121 like: Option<&dyn Array>,
122 ) -> VortexResult<Option<ArrayRef>> {
123 let downcast_like = like
124 .map(|like| {
125 like.as_opt::<V>().ok_or_else(|| {
126 vortex_err!(
127 "Like array {} does not match requested encoding {}",
128 like.encoding_id(),
129 self.id()
130 )
131 })
132 })
133 .transpose()?;
134
135 let Some(array) =
136 <V::EncodeVTable as EncodeVTable<V>>::encode(&self.0, input, downcast_like)?
137 else {
138 return Ok(None);
139 };
140
141 let input = input.as_ref();
142 if array.len() != input.len() {
143 vortex_bail!(
144 "Array length mismatch after encoding: {} != {}",
145 array.len(),
146 input.len()
147 );
148 }
149 if array.dtype() != input.dtype() {
150 vortex_bail!(
151 "Array dtype mismatch after encoding: {} != {}",
152 array.dtype(),
153 input.dtype()
154 );
155 }
156
157 Ok(Some(array.into_array()))
158 }
159}
160
161impl<V: VTable> Debug for ArrayVTableAdapter<V> {
162 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
163 f.debug_struct("Encoding").field("id", &self.id()).finish()
164 }
165}
166
167impl Display for dyn DynVTable + '_ {
168 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
169 write!(f, "{}", self.id())
170 }
171}
172
173impl PartialEq for dyn DynVTable + '_ {
174 fn eq(&self, other: &Self) -> bool {
175 self.id() == other.id()
176 }
177}
178
179impl Eq for dyn DynVTable + '_ {}
180
181impl dyn DynVTable + '_ {
182 pub fn as_<V: VTable>(&self) -> &V {
183 self.as_any()
184 .downcast_ref::<ArrayVTableAdapter<V>>()
185 .map(|e| &e.0)
186 .vortex_expect("Encoding is not of the expected type")
187 }
188}
189
190pub trait ArrayVTableExt {
191 fn as_vtable(&'static self) -> ArrayVTable;
193
194 fn into_vtable(self) -> ArrayVTable;
196
197 fn to_vtable(&self) -> ArrayVTable
198 where
199 Self: Clone;
200}
201
202impl<V: VTable> ArrayVTableExt for V {
203 fn as_vtable(&'static self) -> ArrayVTable {
204 let dyn_vtable: &'static ArrayVTableAdapter<V> =
205 unsafe { transmute::<&'static V, &'static ArrayVTableAdapter<V>>(self) };
206 ArrayVTable::new_ref(dyn_vtable)
207 }
208
209 fn into_vtable(self) -> ArrayVTable {
210 ArrayVTable::new_arc(Arc::new(ArrayVTableAdapter(self)))
211 }
212
213 fn to_vtable(&self) -> ArrayVTable
214 where
215 Self: Clone,
216 {
217 ArrayVTable::new_arc(Arc::new(ArrayVTableAdapter(self.clone())))
218 }
219}
220
221mod private {
222 use crate::vtable::ArrayVTableAdapter;
223 use crate::vtable::VTable;
224
225 pub trait Sealed {}
226 impl<V: VTable> Sealed for ArrayVTableAdapter<V> {}
227}