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
40impl Debug for dyn LayoutChildren {
41 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
42 f.debug_struct("LayoutChildren")
43 .field("nchildren", &self.nchildren())
44 .finish()
45 }
46}
47
48impl LayoutChildren for Arc<dyn LayoutChildren> {
49 fn to_arc(&self) -> Arc<dyn LayoutChildren> {
50 Arc::clone(self)
51 }
52
53 fn child(&self, idx: usize, dtype: &DType) -> VortexResult<LayoutRef> {
54 self.as_ref().child(idx, dtype)
55 }
56
57 fn child_row_count(&self, idx: usize) -> u64 {
58 self.as_ref().child_row_count(idx)
59 }
60
61 fn nchildren(&self) -> usize {
62 self.as_ref().nchildren()
63 }
64}
65
66#[derive(Clone)]
68pub(crate) struct OwnedLayoutChildren(Vec<LayoutRef>);
69
70impl OwnedLayoutChildren {
71 pub fn layout_children(children: Vec<LayoutRef>) -> Arc<dyn LayoutChildren> {
72 Arc::new(Self(children))
73 }
74}
75
76pub fn layout_children(children: Vec<LayoutRef>) -> Arc<dyn LayoutChildren> {
78 OwnedLayoutChildren::layout_children(children)
79}
80
81impl LayoutChildren for OwnedLayoutChildren {
83 fn to_arc(&self) -> Arc<dyn LayoutChildren> {
84 Arc::new(self.clone())
85 }
86
87 fn child(&self, idx: usize, dtype: &DType) -> VortexResult<LayoutRef> {
88 if idx >= self.0.len() {
89 vortex_bail!("Child index out of bounds: {} of {}", idx, self.0.len());
90 }
91 let child = &self.0[idx];
92 if child.dtype() != dtype {
93 vortex_bail!("Child dtype mismatch: {} != {}", child.dtype(), dtype);
94 }
95 Ok(Arc::clone(child))
96 }
97
98 fn child_row_count(&self, idx: usize) -> u64 {
99 self.0[idx].row_count()
100 }
101
102 fn nchildren(&self) -> usize {
103 self.0.len()
104 }
105}
106
107#[derive(Clone)]
108pub(crate) struct ViewedLayoutChildren {
109 flatbuffer: FlatBuffer,
110 flatbuffer_loc: usize,
111 array_read_ctx: ReadContext,
112 layout_read_ctx: ReadContext,
113 layouts: LayoutRegistry,
114 allow_unknown: bool,
115 session: VortexSession,
116 cache: Arc<[OnceCell<LayoutRef>]>,
117}
118
119impl ViewedLayoutChildren {
120 pub(super) unsafe fn new_unchecked(
126 flatbuffer: FlatBuffer,
127 flatbuffer_loc: usize,
128 array_read_ctx: ReadContext,
129 layout_read_ctx: ReadContext,
130 layouts: LayoutRegistry,
131 allow_unknown: bool,
132 session: VortexSession,
133 ) -> Self {
134 let nchildren = unsafe { fbl::Layout::follow(flatbuffer.as_ref(), flatbuffer_loc) }
136 .children()
137 .unwrap_or_default()
138 .len();
139 let cache = vec![OnceCell::new(); nchildren].into_boxed_slice().into();
140 Self {
141 flatbuffer,
142 flatbuffer_loc,
143 array_read_ctx,
144 layout_read_ctx,
145 layouts,
146 allow_unknown,
147 session,
148 cache,
149 }
150 }
151
152 fn flatbuffer(&self) -> fbl::Layout<'_> {
154 unsafe { fbl::Layout::follow(self.flatbuffer.as_ref(), self.flatbuffer_loc) }
158 }
159
160 fn foreign_layout_from_fb(
161 &self,
162 fb_layout: fbl::Layout<'_>,
163 dtype: &DType,
164 ) -> VortexResult<LayoutRef> {
165 let encoding_id = self
166 .layout_read_ctx
167 .resolve(fb_layout.encoding())
168 .ok_or_else(|| vortex_err!("Encoding not found: {}", fb_layout.encoding()))?;
169
170 let children = fb_layout
171 .children()
172 .unwrap_or_default()
173 .iter()
174 .map(|child| self.foreign_layout_from_fb(child, dtype))
175 .collect::<VortexResult<Vec<_>>>()?;
176
177 Ok(new_foreign_layout(
178 encoding_id,
179 dtype.clone(),
180 fb_layout.row_count(),
181 fb_layout
182 .metadata()
183 .map(|m| m.bytes().to_vec())
184 .unwrap_or_default(),
185 fb_layout
186 .segments()
187 .unwrap_or_default()
188 .iter()
189 .map(SegmentId::from)
190 .collect_vec(),
191 children,
192 ))
193 }
194}
195
196impl LayoutChildren for ViewedLayoutChildren {
197 fn to_arc(&self) -> Arc<dyn LayoutChildren> {
198 Arc::new(self.clone())
199 }
200
201 fn child(&self, idx: usize, dtype: &DType) -> VortexResult<LayoutRef> {
202 if idx >= self.nchildren() {
203 vortex_bail!("Child index out of bounds: {} of {}", idx, self.nchildren());
204 }
205
206 let layout_ref = self.cache[idx].get_or_try_init(|| {
207 let fb_child = self.flatbuffer().children().unwrap_or_default().get(idx);
208
209 let viewed_children = unsafe {
212 ViewedLayoutChildren::new_unchecked(
213 self.flatbuffer.clone(),
214 fb_child._tab.loc(),
215 self.array_read_ctx.clone(),
216 self.layout_read_ctx.clone(),
217 self.layouts.clone(),
218 self.allow_unknown,
219 self.session.clone(),
220 )
221 };
222
223 let encoding_id = self
224 .layout_read_ctx
225 .resolve(fb_child.encoding())
226 .ok_or_else(|| {
227 vortex_err!("Unknown layout encoding index: {}", fb_child.encoding())
228 })?;
229 let Some(encoding) = self.layouts.find(&encoding_id) else {
230 if self.allow_unknown {
231 return viewed_children.foreign_layout_from_fb(fb_child, dtype);
232 }
233 vortex_bail!("Unknown layout encoding: {encoding_id}");
234 };
235
236 let build_ctx = LayoutBuildContext {
237 session: &self.session,
238 array_read_ctx: &self.array_read_ctx,
239 };
240 encoding.build(
241 dtype,
242 fb_child.row_count(),
243 fb_child
244 .metadata()
245 .map(|m| m.bytes())
246 .unwrap_or_else(|| &[]),
247 fb_child
248 .segments()
249 .unwrap_or_default()
250 .iter()
251 .map(SegmentId::from)
252 .collect_vec(),
253 &viewed_children,
254 &build_ctx,
255 )
256 })?;
257 Ok(Arc::clone(layout_ref))
258 }
259
260 fn child_row_count(&self, idx: usize) -> u64 {
261 self.flatbuffer()
264 .children()
265 .unwrap_or_default()
266 .get(idx)
267 .row_count()
268 }
269
270 fn nchildren(&self) -> usize {
271 self.cache.len()
272 }
273}