vortex_layout/
children.rs1use std::fmt::Debug;
5use std::fmt::Formatter;
6use std::sync::Arc;
7
8use flatbuffers::Follow;
9use itertools::Itertools;
10use once_cell::sync::OnceCell;
11use vortex_array::dtype::DType;
12use vortex_error::VortexResult;
13use vortex_error::vortex_bail;
14use vortex_error::vortex_err;
15use vortex_flatbuffers::FlatBuffer;
16use vortex_flatbuffers::layout as fbl;
17use vortex_session::VortexSession;
18use vortex_session::registry::ReadContext;
19
20use crate::LayoutBuildContext;
21use crate::LayoutRef;
22use crate::layouts::foreign::new_foreign_layout;
23use crate::segments::SegmentId;
24use crate::session::LayoutRegistry;
25
26pub trait LayoutChildren: 'static + Send + Sync {
31 fn to_arc(&self) -> Arc<dyn LayoutChildren>;
32
33 fn child(&self, idx: usize, dtype: &DType) -> VortexResult<LayoutRef>;
34
35 fn child_row_count(&self, idx: usize) -> u64;
36
37 fn nchildren(&self) -> usize;
38
39 fn child_is_indivisible(&self, _idx: usize) -> bool {
46 false
47 }
48}
49
50impl Debug for dyn LayoutChildren {
51 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
52 f.debug_struct("LayoutChildren")
53 .field("nchildren", &self.nchildren())
54 .finish()
55 }
56}
57
58impl LayoutChildren for Arc<dyn LayoutChildren> {
59 fn to_arc(&self) -> Arc<dyn LayoutChildren> {
60 Arc::clone(self)
61 }
62
63 fn child(&self, idx: usize, dtype: &DType) -> VortexResult<LayoutRef> {
64 self.as_ref().child(idx, dtype)
65 }
66
67 fn child_row_count(&self, idx: usize) -> u64 {
68 self.as_ref().child_row_count(idx)
69 }
70
71 fn nchildren(&self) -> usize {
72 self.as_ref().nchildren()
73 }
74
75 fn child_is_indivisible(&self, idx: usize) -> bool {
76 self.as_ref().child_is_indivisible(idx)
77 }
78}
79
80#[derive(Clone)]
82pub(crate) struct OwnedLayoutChildren(Vec<LayoutRef>);
83
84impl OwnedLayoutChildren {
85 pub fn layout_children(children: Vec<LayoutRef>) -> Arc<dyn LayoutChildren> {
86 Arc::new(Self(children))
87 }
88}
89
90pub fn layout_children(children: Vec<LayoutRef>) -> Arc<dyn LayoutChildren> {
92 OwnedLayoutChildren::layout_children(children)
93}
94
95impl LayoutChildren for OwnedLayoutChildren {
97 fn to_arc(&self) -> Arc<dyn LayoutChildren> {
98 Arc::new(self.clone())
99 }
100
101 fn child(&self, idx: usize, dtype: &DType) -> VortexResult<LayoutRef> {
102 if idx >= self.0.len() {
103 vortex_bail!("Child index out of bounds: {} of {}", idx, self.0.len());
104 }
105 let child = &self.0[idx];
106 if child.dtype() != dtype {
107 vortex_bail!("Child dtype mismatch: {} != {}", child.dtype(), dtype);
108 }
109 Ok(Arc::clone(child))
110 }
111
112 fn child_row_count(&self, idx: usize) -> u64 {
113 self.0[idx].row_count()
114 }
115
116 fn nchildren(&self) -> usize {
117 self.0.len()
118 }
119
120 fn child_is_indivisible(&self, idx: usize) -> bool {
121 self.0[idx].dyn_is_indivisible()
122 }
123}
124
125#[derive(Clone)]
126pub(crate) struct ViewedLayoutChildren {
127 flatbuffer: FlatBuffer,
128 flatbuffer_loc: usize,
129 array_read_ctx: ReadContext,
130 layout_read_ctx: ReadContext,
131 layouts: LayoutRegistry,
132 allow_unknown: bool,
133 session: VortexSession,
134 cache: Arc<[OnceCell<LayoutRef>]>,
135 indivisible: Arc<[bool]>,
138}
139
140impl ViewedLayoutChildren {
141 pub(super) unsafe fn new_unchecked(
147 flatbuffer: FlatBuffer,
148 flatbuffer_loc: usize,
149 array_read_ctx: ReadContext,
150 layout_read_ctx: ReadContext,
151 layouts: LayoutRegistry,
152 allow_unknown: bool,
153 session: VortexSession,
154 ) -> Self {
155 let fb_children = unsafe { fbl::Layout::follow(flatbuffer.as_ref(), flatbuffer_loc) }
157 .children()
158 .unwrap_or_default();
159 let cache = vec![OnceCell::new(); fb_children.len()]
160 .into_boxed_slice()
161 .into();
162 let indivisible = fb_children
165 .iter()
166 .map(|child| {
167 layout_read_ctx
168 .resolve(child.encoding())
169 .and_then(|encoding_id| layouts.get(&encoding_id))
170 .is_some_and(|encoding| encoding.is_indivisible())
171 })
172 .collect::<Arc<[bool]>>();
173 Self {
174 flatbuffer,
175 flatbuffer_loc,
176 array_read_ctx,
177 layout_read_ctx,
178 layouts,
179 allow_unknown,
180 session,
181 cache,
182 indivisible,
183 }
184 }
185
186 fn flatbuffer(&self) -> fbl::Layout<'_> {
188 unsafe { fbl::Layout::follow(self.flatbuffer.as_ref(), self.flatbuffer_loc) }
192 }
193
194 fn foreign_layout_from_fb(
195 &self,
196 fb_layout: fbl::Layout<'_>,
197 dtype: &DType,
198 ) -> VortexResult<LayoutRef> {
199 let encoding_id = self
200 .layout_read_ctx
201 .resolve(fb_layout.encoding())
202 .ok_or_else(|| vortex_err!("Encoding not found: {}", fb_layout.encoding()))?;
203
204 let children = fb_layout
205 .children()
206 .unwrap_or_default()
207 .iter()
208 .map(|child| self.foreign_layout_from_fb(child, dtype))
209 .collect::<VortexResult<Vec<_>>>()?;
210
211 Ok(new_foreign_layout(
212 encoding_id,
213 dtype.clone(),
214 fb_layout.row_count(),
215 fb_layout
216 .metadata()
217 .map(|m| m.bytes().to_vec())
218 .unwrap_or_default(),
219 fb_layout
220 .segments()
221 .unwrap_or_default()
222 .iter()
223 .map(SegmentId::from)
224 .collect_vec(),
225 children,
226 ))
227 }
228}
229
230impl LayoutChildren for ViewedLayoutChildren {
231 fn to_arc(&self) -> Arc<dyn LayoutChildren> {
232 Arc::new(self.clone())
233 }
234
235 fn child(&self, idx: usize, dtype: &DType) -> VortexResult<LayoutRef> {
236 if idx >= self.nchildren() {
237 vortex_bail!("Child index out of bounds: {} of {}", idx, self.nchildren());
238 }
239
240 let layout_ref = self.cache[idx].get_or_try_init(|| {
241 let fb_child = self.flatbuffer().children().unwrap_or_default().get(idx);
242
243 let viewed_children = unsafe {
246 ViewedLayoutChildren::new_unchecked(
247 self.flatbuffer.clone(),
248 fb_child._tab.loc(),
249 self.array_read_ctx.clone(),
250 self.layout_read_ctx.clone(),
251 self.layouts.clone(),
252 self.allow_unknown,
253 self.session.clone(),
254 )
255 };
256
257 let encoding_id = self
258 .layout_read_ctx
259 .resolve(fb_child.encoding())
260 .ok_or_else(|| {
261 vortex_err!("Unknown layout encoding index: {}", fb_child.encoding())
262 })?;
263 let Some(encoding) = self.layouts.get(&encoding_id) else {
264 if self.allow_unknown {
265 return viewed_children.foreign_layout_from_fb(fb_child, dtype);
266 }
267 vortex_bail!("Unknown layout encoding: {encoding_id}");
268 };
269
270 let build_ctx = LayoutBuildContext {
271 session: &self.session,
272 array_read_ctx: &self.array_read_ctx,
273 };
274 encoding.build(
275 dtype,
276 fb_child.row_count(),
277 fb_child
278 .metadata()
279 .map(|m| m.bytes())
280 .unwrap_or_else(|| &[]),
281 fb_child
282 .segments()
283 .unwrap_or_default()
284 .iter()
285 .map(SegmentId::from)
286 .collect_vec(),
287 &viewed_children,
288 &build_ctx,
289 )
290 })?;
291 Ok(Arc::clone(layout_ref))
292 }
293
294 fn child_row_count(&self, idx: usize) -> u64 {
295 self.flatbuffer()
298 .children()
299 .unwrap_or_default()
300 .get(idx)
301 .row_count()
302 }
303
304 fn nchildren(&self) -> usize {
305 self.cache.len()
306 }
307
308 fn child_is_indivisible(&self, idx: usize) -> bool {
309 self.indivisible.get(idx).copied().unwrap_or(false)
310 }
311}