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
76impl LayoutChildren for OwnedLayoutChildren {
78 fn to_arc(&self) -> Arc<dyn LayoutChildren> {
79 Arc::new(self.clone())
80 }
81
82 fn child(&self, idx: usize, dtype: &DType) -> VortexResult<LayoutRef> {
83 if idx >= self.0.len() {
84 vortex_bail!("Child index out of bounds: {} of {}", idx, self.0.len());
85 }
86 let child = &self.0[idx];
87 if child.dtype() != dtype {
88 vortex_bail!("Child dtype mismatch: {} != {}", child.dtype(), dtype);
89 }
90 Ok(Arc::clone(child))
91 }
92
93 fn child_row_count(&self, idx: usize) -> u64 {
94 self.0[idx].row_count()
95 }
96
97 fn nchildren(&self) -> usize {
98 self.0.len()
99 }
100}
101
102#[derive(Clone)]
103pub(crate) struct ViewedLayoutChildren {
104 flatbuffer: FlatBuffer,
105 flatbuffer_loc: usize,
106 array_read_ctx: ReadContext,
107 layout_read_ctx: ReadContext,
108 layouts: LayoutRegistry,
109 allow_unknown: bool,
110 session: VortexSession,
111 cache: Arc<[OnceCell<LayoutRef>]>,
112}
113
114impl ViewedLayoutChildren {
115 pub(super) unsafe fn new_unchecked(
121 flatbuffer: FlatBuffer,
122 flatbuffer_loc: usize,
123 array_read_ctx: ReadContext,
124 layout_read_ctx: ReadContext,
125 layouts: LayoutRegistry,
126 allow_unknown: bool,
127 session: VortexSession,
128 ) -> Self {
129 let nchildren = unsafe { fbl::Layout::follow(flatbuffer.as_ref(), flatbuffer_loc) }
131 .children()
132 .unwrap_or_default()
133 .len();
134 let cache = vec![OnceCell::new(); nchildren].into_boxed_slice().into();
135 Self {
136 flatbuffer,
137 flatbuffer_loc,
138 array_read_ctx,
139 layout_read_ctx,
140 layouts,
141 allow_unknown,
142 session,
143 cache,
144 }
145 }
146
147 fn flatbuffer(&self) -> fbl::Layout<'_> {
149 unsafe { fbl::Layout::follow(self.flatbuffer.as_ref(), self.flatbuffer_loc) }
153 }
154
155 fn foreign_layout_from_fb(
156 &self,
157 fb_layout: fbl::Layout<'_>,
158 dtype: &DType,
159 ) -> VortexResult<LayoutRef> {
160 let encoding_id = self
161 .layout_read_ctx
162 .resolve(fb_layout.encoding())
163 .ok_or_else(|| vortex_err!("Encoding not found: {}", fb_layout.encoding()))?;
164
165 let children = fb_layout
166 .children()
167 .unwrap_or_default()
168 .iter()
169 .map(|child| self.foreign_layout_from_fb(child, dtype))
170 .collect::<VortexResult<Vec<_>>>()?;
171
172 Ok(new_foreign_layout(
173 encoding_id,
174 dtype.clone(),
175 fb_layout.row_count(),
176 fb_layout
177 .metadata()
178 .map(|m| m.bytes().to_vec())
179 .unwrap_or_default(),
180 fb_layout
181 .segments()
182 .unwrap_or_default()
183 .iter()
184 .map(SegmentId::from)
185 .collect_vec(),
186 children,
187 ))
188 }
189}
190
191impl LayoutChildren for ViewedLayoutChildren {
192 fn to_arc(&self) -> Arc<dyn LayoutChildren> {
193 Arc::new(self.clone())
194 }
195
196 fn child(&self, idx: usize, dtype: &DType) -> VortexResult<LayoutRef> {
197 if idx >= self.nchildren() {
198 vortex_bail!("Child index out of bounds: {} of {}", idx, self.nchildren());
199 }
200
201 let layout_ref = self.cache[idx].get_or_try_init(|| {
202 let fb_child = self.flatbuffer().children().unwrap_or_default().get(idx);
203
204 let viewed_children = unsafe {
207 ViewedLayoutChildren::new_unchecked(
208 self.flatbuffer.clone(),
209 fb_child._tab.loc(),
210 self.array_read_ctx.clone(),
211 self.layout_read_ctx.clone(),
212 self.layouts.clone(),
213 self.allow_unknown,
214 self.session.clone(),
215 )
216 };
217
218 let encoding_id = self
219 .layout_read_ctx
220 .resolve(fb_child.encoding())
221 .ok_or_else(|| vortex_err!("Encoding not found: {}", fb_child.encoding()))?;
222 let Some(encoding) = self.layouts.find(&encoding_id) else {
223 if self.allow_unknown {
224 return viewed_children.foreign_layout_from_fb(fb_child, dtype);
225 }
226 return Err(vortex_err!(
227 "Encoding not found in registry: {}",
228 fb_child.encoding()
229 ));
230 };
231
232 let build_ctx = LayoutBuildContext {
233 session: &self.session,
234 array_read_ctx: &self.array_read_ctx,
235 };
236 encoding.build(
237 dtype,
238 fb_child.row_count(),
239 fb_child
240 .metadata()
241 .map(|m| m.bytes())
242 .unwrap_or_else(|| &[]),
243 fb_child
244 .segments()
245 .unwrap_or_default()
246 .iter()
247 .map(SegmentId::from)
248 .collect_vec(),
249 &viewed_children,
250 &build_ctx,
251 )
252 })?;
253 Ok(Arc::clone(layout_ref))
254 }
255
256 fn child_row_count(&self, idx: usize) -> u64 {
257 self.flatbuffer()
260 .children()
261 .unwrap_or_default()
262 .get(idx)
263 .row_count()
264 }
265
266 fn nchildren(&self) -> usize {
267 self.cache.len()
268 }
269}