vortex_layout/layouts/struct_/
mod.rs1mod eval_expr;
2mod reader;
3pub mod writer;
4
5use std::collections::BTreeSet;
6use std::sync::Arc;
7
8use reader::StructReader;
9use vortex_array::ArrayContext;
10use vortex_dtype::{DType, Field, FieldMask};
11use vortex_error::{VortexResult, vortex_bail};
12
13use crate::data::Layout;
14use crate::reader::{LayoutReader, LayoutReaderExt};
15use crate::segments::{AsyncSegmentReader, RequiredSegmentKind, SegmentCollector};
16use crate::vtable::LayoutVTable;
17use crate::{LayoutId, STRUCT_LAYOUT_ID};
18
19#[derive(Debug)]
20pub struct StructLayout;
21
22impl LayoutVTable for StructLayout {
23 fn id(&self) -> LayoutId {
24 STRUCT_LAYOUT_ID
25 }
26
27 fn reader(
28 &self,
29 layout: Layout,
30 ctx: ArrayContext,
31 segment_reader: Arc<dyn AsyncSegmentReader>,
32 ) -> VortexResult<Arc<dyn LayoutReader>> {
33 Ok(StructReader::try_new(layout, ctx, segment_reader)?.into_arc())
34 }
35
36 fn register_splits(
37 &self,
38 layout: &Layout,
39 field_mask: &[FieldMask],
40 row_offset: u64,
41 splits: &mut BTreeSet<u64>,
42 ) -> VortexResult<()> {
43 for_all_matching_children(layout, field_mask, |mask, child| {
44 child.register_splits(&[mask], row_offset, splits)
45 })?;
46 Ok(())
47 }
48
49 fn required_segments(
50 &self,
51 layout: &Layout,
52 row_offset: u64,
53 filter_field_mask: &[FieldMask],
54 projection_field_mask: &[FieldMask],
55 segments: &mut SegmentCollector,
56 ) -> VortexResult<()> {
57 for_all_matching_children(layout, filter_field_mask, |field_mask, child| {
58 child.required_segments(
59 row_offset,
60 &[field_mask],
61 &[],
62 &mut segments.with_priority_hint(RequiredSegmentKind::Filter),
63 )
64 })?;
65 for_all_matching_children(layout, projection_field_mask, |field_mask, child| {
66 child.required_segments(
67 row_offset,
68 &[],
69 &[field_mask],
70 &mut segments.with_priority_hint(RequiredSegmentKind::Projection),
71 )
72 })?;
73 Ok(())
74 }
75}
76
77fn for_all_matching_children<F>(
78 layout: &Layout,
79 field_mask: &[FieldMask],
80 mut per_child: F,
81) -> VortexResult<()>
82where
83 F: FnMut(FieldMask, Layout) -> VortexResult<()>,
84{
85 let DType::Struct(dtype, _) = layout.dtype() else {
86 vortex_bail!("Mismatched dtype {} for struct layout", layout.dtype());
87 };
88
89 if field_mask.iter().any(|mask| mask.matches_all()) {
91 for (idx, field_dtype) in dtype.fields().enumerate() {
92 let child = layout.child(idx, field_dtype, dtype.field_name(idx)?)?;
93 per_child(FieldMask::All, child)?;
94 }
95 return Ok(());
96 }
97
98 for path in field_mask {
100 let Some(field) = path.starting_field()? else {
101 continue;
103 };
104 let Field::Name(field_name) = field else {
105 vortex_bail!("Expected field name, got {:?}", field);
106 };
107
108 let idx = dtype.find(field_name)?;
109 let child = layout.child(idx, dtype.field_by_index(idx)?, field_name)?;
110 per_child(path.clone().step_into()?, child)?;
111 }
112
113 Ok(())
114}