vortex_layout/
flatbuffers.rs1use std::env;
5use std::sync::LazyLock;
6
7use flatbuffers::FlatBufferBuilder;
8use flatbuffers::VerifierOptions;
9use flatbuffers::WIPOffset;
10use flatbuffers::root_with_opts;
11use vortex_array::ArrayContext;
12use vortex_dtype::DType;
13use vortex_error::VortexResult;
14use vortex_error::vortex_err;
15use vortex_flatbuffers::FlatBuffer;
16use vortex_flatbuffers::FlatBufferRoot;
17use vortex_flatbuffers::WriteFlatBuffer;
18use vortex_flatbuffers::layout;
19
20use crate::Layout;
21use crate::LayoutContext;
22use crate::LayoutRef;
23use crate::children::ViewedLayoutChildren;
24use crate::segments::SegmentId;
25use crate::session::LayoutRegistry;
26
27static LAYOUT_VERIFIER: LazyLock<VerifierOptions> = LazyLock::new(|| {
28 VerifierOptions {
29 max_tables: env::var("VORTEX_MAX_LAYOUT_TABLES")
31 .ok()
32 .and_then(|lmt| lmt.parse::<usize>().ok())
33 .unwrap_or(1000000),
34 max_depth: env::var("VORTEX_MAX_LAYOUT_DEPTH")
35 .ok()
36 .and_then(|lmt| lmt.parse::<usize>().ok())
37 .unwrap_or(64),
38 max_apparent_size: 1 << 31,
40 ignore_missing_null_terminator: false,
41 }
42});
43
44pub fn layout_from_flatbuffer(
46 flatbuffer: FlatBuffer,
47 dtype: &DType,
48 layout_ctx: &LayoutContext,
49 ctx: &ArrayContext,
50 layouts: &LayoutRegistry,
51) -> VortexResult<LayoutRef> {
52 let fb_layout = root_with_opts::<layout::Layout>(&LAYOUT_VERIFIER, &flatbuffer)?;
53 let encoding_id = layout_ctx
54 .resolve(fb_layout.encoding())
55 .ok_or_else(|| vortex_err!("Invalid encoding ID: {}", fb_layout.encoding()))?;
56 let encoding = layouts
57 .find(&encoding_id)
58 .ok_or_else(|| vortex_err!("Invalid encoding ID: {}", fb_layout.encoding()))?;
59
60 let viewed_children = unsafe {
62 ViewedLayoutChildren::new_unchecked(
63 flatbuffer.clone(),
64 fb_layout._tab.loc(),
65 ctx.clone(),
66 layout_ctx.clone(),
67 layouts.clone(),
68 )
69 };
70
71 let layout = encoding.build(
72 dtype,
73 fb_layout.row_count(),
74 fb_layout
75 .metadata()
76 .map(|m| m.bytes())
77 .unwrap_or_else(|| &[]),
78 fb_layout
79 .segments()
80 .unwrap_or_default()
81 .iter()
82 .map(SegmentId::from)
83 .collect(),
84 &viewed_children,
85 ctx,
86 )?;
87
88 Ok(layout)
89}
90
91impl dyn Layout + '_ {
92 pub fn flatbuffer_writer<'a>(
94 &'a self,
95 ctx: &'a LayoutContext,
96 ) -> impl WriteFlatBuffer<Target<'a> = layout::Layout<'a>> + FlatBufferRoot + 'a {
97 LayoutFlatBufferWriter { layout: self, ctx }
98 }
99}
100
101struct LayoutFlatBufferWriter<'a> {
103 layout: &'a dyn Layout,
104 ctx: &'a LayoutContext,
105}
106
107impl FlatBufferRoot for LayoutFlatBufferWriter<'_> {}
108
109impl WriteFlatBuffer for LayoutFlatBufferWriter<'_> {
110 type Target<'fb> = layout::Layout<'fb>;
111
112 fn write_flatbuffer<'fb>(
113 &self,
114 fbb: &mut FlatBufferBuilder<'fb>,
115 ) -> VortexResult<WIPOffset<Self::Target<'fb>>> {
116 let child_layouts = self.layout.children()?;
118 let children = child_layouts
119 .iter()
120 .map(|layout| {
121 LayoutFlatBufferWriter {
122 layout: layout.as_ref(),
123 ctx: self.ctx,
124 }
125 .write_flatbuffer(fbb)
126 })
127 .collect::<VortexResult<Vec<_>>>()?;
128 let children = (!children.is_empty()).then(|| fbb.create_vector(&children));
129
130 let metadata = self.layout.metadata();
132 let metadata = (!metadata.is_empty()).then(|| fbb.create_vector(&metadata));
133
134 let segments = self
135 .layout
136 .segment_ids()
137 .into_iter()
138 .map(|s| *s)
139 .collect::<Vec<_>>();
140 let segments = (!segments.is_empty()).then(|| fbb.create_vector(&segments));
141
142 let encoding = self.ctx.intern(&self.layout.encoding_id()).ok_or_else(|| {
144 vortex_err!(
145 "Failed to intern layout encoding ID: {}",
146 self.layout.encoding_id()
147 )
148 })?;
149
150 Ok(layout::Layout::create(
151 fbb,
152 &layout::LayoutArgs {
153 encoding,
154 row_count: self.layout.row_count(),
155 metadata,
156 children,
157 segments,
158 },
159 ))
160 }
161}