vortex_file/footer/
mod.rs1mod field_sizes;
12mod file_layout;
13mod file_statistics;
14mod postscript;
15mod segment;
16
17use std::sync::Arc;
18
19mod serializer;
20pub use serializer::*;
21mod deserializer;
22pub use deserializer::*;
23pub use field_sizes::CompressedFieldSizes;
24pub use file_statistics::FileStatistics;
25use flatbuffers::root;
26use itertools::Itertools;
27pub use segment::*;
28use vortex_array::ArrayId;
29use vortex_array::dtype::DType;
30use vortex_buffer::ByteBuffer;
31use vortex_error::VortexResult;
32use vortex_error::vortex_bail;
33use vortex_error::vortex_err;
34use vortex_flatbuffers::FlatBuffer;
35use vortex_flatbuffers::footer as fb;
36use vortex_layout::LayoutEncodingId;
37use vortex_layout::LayoutRef;
38use vortex_layout::layout_from_flatbuffer_with_options;
39use vortex_session::VortexSession;
40use vortex_session::registry::ReadContext;
41
42#[derive(Debug, Clone)]
44pub struct Footer {
45 root_layout: LayoutRef,
46 segments: Arc<[SegmentSpec]>,
47 statistics: Option<FileStatistics>,
48 array_read_ctx: ReadContext,
50 approx_byte_size: Option<usize>,
52}
53
54impl Footer {
55 pub fn new(
56 root_layout: LayoutRef,
57 segments: Arc<[SegmentSpec]>,
58 statistics: Option<FileStatistics>,
59 array_read_ctx: ReadContext,
60 ) -> Self {
61 Self {
62 root_layout,
63 segments,
64 statistics,
65 array_read_ctx,
66 approx_byte_size: None,
67 }
68 }
69
70 pub(crate) fn with_approx_byte_size(mut self, approx_byte_size: usize) -> Self {
71 self.approx_byte_size = Some(approx_byte_size);
72 self
73 }
74
75 pub(crate) fn from_flatbuffer(
77 footer_bytes: FlatBuffer,
78 layout_bytes: FlatBuffer,
79 dtype: DType,
80 statistics: Option<FileStatistics>,
81 session: &VortexSession,
82 ) -> VortexResult<Self> {
83 let approx_byte_size = footer_bytes.len() + layout_bytes.len();
84 let fb_footer = root::<fb::Footer>(&footer_bytes)?;
85
86 let layout_specs = fb_footer.layout_specs();
88 #[expect(clippy::disallowed_methods, reason = "interning a dynamic id")]
89 let layout_ids: Arc<[_]> = layout_specs
90 .iter()
91 .flat_map(|e| e.iter())
92 .map(|encoding| LayoutEncodingId::new(encoding.id()))
93 .collect();
94 let layout_read_ctx = ReadContext::new(layout_ids);
95
96 let array_specs = fb_footer.array_specs();
98 #[expect(clippy::disallowed_methods, reason = "interning a dynamic id")]
99 let array_ids: Arc<[_]> = array_specs
100 .iter()
101 .flat_map(|e| e.iter())
102 .map(|encoding| ArrayId::new(encoding.id()))
103 .collect();
104 let array_read_ctx = ReadContext::new(array_ids);
105
106 let root_layout = layout_from_flatbuffer_with_options(
107 layout_bytes,
108 &dtype,
109 &layout_read_ctx,
110 &array_read_ctx,
111 session,
112 session.allows_unknown(),
113 )?;
114
115 let segments: Arc<[SegmentSpec]> = fb_footer
116 .segment_specs()
117 .ok_or_else(|| vortex_err!("FileLayout missing segment specs"))?
118 .iter()
119 .map(SegmentSpec::try_from)
120 .try_collect()?;
121
122 if !segments.is_sorted_by_key(|segment| segment.offset) {
124 vortex_bail!("Segment offsets are not ordered");
125 }
126
127 Ok(Self {
128 root_layout,
129 segments,
130 statistics,
131 array_read_ctx,
132 approx_byte_size: Some(approx_byte_size),
133 })
134 }
135
136 pub fn layout(&self) -> &LayoutRef {
138 &self.root_layout
139 }
140
141 pub fn segment_map(&self) -> &Arc<[SegmentSpec]> {
143 &self.segments
144 }
145
146 pub fn statistics(&self) -> Option<&FileStatistics> {
148 self.statistics.as_ref()
149 }
150
151 pub fn compressed_field_sizes(&self) -> VortexResult<CompressedFieldSizes> {
157 CompressedFieldSizes::try_new(&self.root_layout, &self.segments)
158 }
159
160 pub fn dtype(&self) -> &DType {
162 self.root_layout.dtype()
163 }
164
165 pub fn approx_byte_size(&self) -> Option<usize> {
167 self.approx_byte_size
168 }
169
170 pub fn row_count(&self) -> u64 {
172 self.root_layout.row_count()
173 }
174
175 pub fn into_serializer(self) -> FooterSerializer {
177 FooterSerializer::new(self)
178 }
179
180 pub fn deserializer(eof_buffer: ByteBuffer, session: VortexSession) -> FooterDeserializer {
182 FooterDeserializer::new(eof_buffer, session)
183 }
184}