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