22// SPDX-FileCopyrightText: Copyright the Vortex contributors
33
44use std:: sync:: Arc ;
5- use std:: sync:: OnceLock ;
65
7- use vortex_array:: DeserializeMetadata ;
8- use vortex_array:: SerializeMetadata ;
6+ use vortex_array:: EmptyMetadata ;
97use vortex_array:: dtype:: DType ;
10- use vortex_array:: dtype:: TryFromBytes ;
118use vortex_buffer:: ByteBuffer ;
12- use vortex_error:: VortexExpect ;
139use vortex_error:: VortexResult ;
1410use vortex_error:: vortex_bail;
1511use vortex_error:: vortex_panic;
@@ -19,12 +15,11 @@ use vortex_session::registry::ReadContext;
1915use crate :: LayoutChildType ;
2016use crate :: LayoutEncodingRef ;
2117use crate :: LayoutId ;
18+ use crate :: LayoutReaderContext ;
2219use crate :: LayoutReaderRef ;
2320use crate :: LayoutRef ;
2421use crate :: VTable ;
2522use crate :: children:: LayoutChildren ;
26- use crate :: layouts:: array_tree:: ArrayTreesSource ;
27- use crate :: layouts:: array_tree:: reader:: ArrayTreeFlatReader ;
2823use crate :: layouts:: flat:: FlatLayout ;
2924use crate :: segments:: SegmentId ;
3025use crate :: segments:: SegmentSource ;
@@ -36,44 +31,34 @@ vtable!(ArrayTreeFlat);
3631#[ derive( Debug ) ]
3732pub struct ArrayTreeFlatLayoutEncoding ;
3833
39- /// A flat layout variant that stores its compact encoding tree separately from the data segment.
34+ /// A flat layout variant that retrieves its compact encoding tree from a sibling layout's
35+ /// VarBin payload rather than from the data segment trailer.
4036///
4137/// At write time, the compact flatbuffer (encoding tree + buffer descriptors, no stats) is
42- /// stored in this layout and later collected by [`super::ArrayTreeLayout`] into a shared VarBin
43- /// array.
38+ /// attached to this layout in memory and later collected by [`super::ArrayTreeLayout`] into
39+ /// a struct array keyed by segment ID .
4440///
45- /// At read time, the compact flatbuffer is retrieved from the shared [`ArrayTreesSource`]
46- /// (injected by the parent [`super::ArrayTreeLayout`]'s reader-construction walk) rather than
47- /// being parsed from the data segment. This avoids fetching the segment for decode planning
48- /// and prevents device-to-host copies for device-resident buffers .
41+ /// At read time, this layout's reader looks up its compact tree in a shared
42+ /// [`super::ArrayTreesSource`] using its own [`SegmentId`]. Construction requires that an
43+ /// ancestor [`super::ArrayTreeLayout`] has registered a reader-builder override against
44+ /// this encoding's ID — this layout has no useful default reader .
4945#[ derive( Clone , Debug ) ]
5046pub struct ArrayTreeFlatLayout {
5147 inner : FlatLayout ,
52- chunk_idx : usize ,
5348 /// The compact flatbuffer produced at write time. Not persisted — only used to communicate
5449 /// between the leaf strategy and the collector strategy via the layout tree.
5550 compact_tree : Option < ByteBuffer > ,
56- /// Shared source for compact flatbuffers, injected by the parent [`super::ArrayTreeLayout`]
57- /// during reader construction.
58- source : OnceLock < Arc < ArrayTreesSource > > ,
5951}
6052
6153impl ArrayTreeFlatLayout {
6254 /// Creates a new layout at write time with a compact flatbuffer.
63- pub fn new ( inner : FlatLayout , chunk_idx : usize , compact_tree : ByteBuffer ) -> Self {
55+ pub fn new ( inner : FlatLayout , compact_tree : ByteBuffer ) -> Self {
6456 Self {
6557 inner,
66- chunk_idx,
6758 compact_tree : Some ( compact_tree) ,
68- source : OnceLock :: new ( ) ,
6959 }
7060 }
7161
72- /// Returns the chunk index of this layout in the array trees VarBin.
73- pub fn chunk_idx ( & self ) -> usize {
74- self . chunk_idx
75- }
76-
7762 /// Returns the compact flatbuffer, if available (write-time only).
7863 pub fn compact_tree ( & self ) -> Option < & ByteBuffer > {
7964 self . compact_tree . as_ref ( )
@@ -83,45 +68,12 @@ impl ArrayTreeFlatLayout {
8368 pub fn inner ( & self ) -> & FlatLayout {
8469 & self . inner
8570 }
86-
87- /// Sets the shared array trees source. Called by the parent [`super::ArrayTreeLayout`]
88- /// during the reader-construction injection walk.
89- pub fn set_source ( & self , source : Arc < ArrayTreesSource > ) {
90- // Ignore if already set (e.g., in tests or double-init scenarios).
91- drop ( self . source . set ( source) ) ;
92- }
93-
94- /// Returns the shared array trees source, if set.
95- pub fn source ( & self ) -> Option < & Arc < ArrayTreesSource > > {
96- self . source . get ( )
97- }
98- }
99-
100- /// Metadata for [`ArrayTreeFlatLayout`]: stores the chunk index.
101- #[ derive( Debug , Clone , PartialEq , Eq ) ]
102- pub struct ArrayTreeFlatMetadata {
103- pub chunk_idx : u32 ,
104- }
105-
106- impl SerializeMetadata for ArrayTreeFlatMetadata {
107- fn serialize ( self ) -> Vec < u8 > {
108- self . chunk_idx . to_le_bytes ( ) . to_vec ( )
109- }
110- }
111-
112- impl DeserializeMetadata for ArrayTreeFlatMetadata {
113- type Output = Self ;
114-
115- fn deserialize ( metadata : & [ u8 ] ) -> VortexResult < Self :: Output > {
116- let chunk_idx = u32:: try_from_le_bytes ( & metadata[ 0 ..4 ] ) ?;
117- Ok ( Self { chunk_idx } )
118- }
11971}
12072
12173impl VTable for ArrayTreeFlat {
12274 type Layout = ArrayTreeFlatLayout ;
12375 type Encoding = ArrayTreeFlatLayoutEncoding ;
124- type Metadata = ArrayTreeFlatMetadata ;
76+ type Metadata = EmptyMetadata ;
12577
12678 fn id ( _encoding : & Self :: Encoding ) -> LayoutId {
12779 LayoutId :: new_static ( "vortex.array_tree_flat" )
@@ -139,10 +91,8 @@ impl VTable for ArrayTreeFlat {
13991 layout. inner . dtype ( )
14092 }
14193
142- fn metadata ( layout : & Self :: Layout ) -> Self :: Metadata {
143- ArrayTreeFlatMetadata {
144- chunk_idx : u32:: try_from ( layout. chunk_idx ) . vortex_expect ( "chunk_idx must fit in u32" ) ,
145- }
94+ fn metadata ( _layout : & Self :: Layout ) -> Self :: Metadata {
95+ EmptyMetadata
14696 }
14797
14898 fn segment_ids ( layout : & Self :: Layout ) -> Vec < SegmentId > {
@@ -162,24 +112,27 @@ impl VTable for ArrayTreeFlat {
162112 }
163113
164114 fn new_reader (
165- layout : & Self :: Layout ,
166- name : Arc < str > ,
167- segment_source : Arc < dyn SegmentSource > ,
168- session : & VortexSession ,
115+ _layout : & Self :: Layout ,
116+ _name : Arc < str > ,
117+ _segment_source : Arc < dyn SegmentSource > ,
118+ _session : & VortexSession ,
119+ _ctx : & LayoutReaderContext ,
169120 ) -> VortexResult < LayoutReaderRef > {
170- Ok ( Arc :: new ( ArrayTreeFlatReader :: new (
171- layout. clone ( ) ,
172- name,
173- segment_source,
174- session. clone ( ) ,
175- ) ) )
121+ // ArrayTreeFlatLayout has no useful default reader. It exists to be intercepted by an
122+ // ancestor ArrayTreeLayout that registers a reader-builder override carrying the
123+ // shared ArrayTreesSource. If the dispatcher reached this method, no such ancestor
124+ // was present in the layout tree.
125+ vortex_bail ! (
126+ "ArrayTreeFlatLayout requires an ancestor ArrayTreeLayout to register a reader \
127+ builder override; this layout cannot be read on its own"
128+ )
176129 }
177130
178131 fn build (
179132 _encoding : & Self :: Encoding ,
180133 dtype : & DType ,
181134 row_count : u64 ,
182- metadata : & ArrayTreeFlatMetadata ,
135+ _metadata : & EmptyMetadata ,
183136 segment_ids : Vec < SegmentId > ,
184137 _children : & dyn LayoutChildren ,
185138 ctx : & ReadContext ,
@@ -189,9 +142,7 @@ impl VTable for ArrayTreeFlat {
189142 }
190143 Ok ( ArrayTreeFlatLayout {
191144 inner : FlatLayout :: new ( row_count, dtype. clone ( ) , segment_ids[ 0 ] , ctx. clone ( ) ) ,
192- chunk_idx : metadata. chunk_idx as usize ,
193145 compact_tree : None ,
194- source : OnceLock :: new ( ) ,
195146 } )
196147 }
197148}
0 commit comments