@@ -7,9 +7,10 @@ use vortex_dtype::{DType, Nullability, PType};
77use vortex_error:: { VortexResult , vortex_bail, vortex_err} ;
88use vortex_vector:: { Vector , VectorMut , VectorMutOps } ;
99
10- use crate :: arrays:: ChunkedArray ;
10+ use crate :: arrays:: { ChunkedArray , PrimitiveArray } ;
1111use crate :: execution:: ExecutionCtx ;
1212use crate :: serde:: ArrayChildren ;
13+ use crate :: validity:: Validity ;
1314use crate :: vtable:: { NotSupported , VTable } ;
1415use crate :: { ArrayOperator , EmptyMetadata , EncodingId , EncodingRef , ToCanonical , vtable} ;
1516
@@ -71,18 +72,19 @@ impl VTable for ChunkedVTable {
7172 let nchunks = children. len ( ) - 1 ;
7273
7374 // The first child contains the row offsets of the chunks
74- let chunk_offsets = children
75+ let chunk_offsets_array = children
7576 . get (
7677 0 ,
7778 & DType :: Primitive ( PType :: U64 , Nullability :: NonNullable ) ,
7879 // 1 extra offset for the end of the last chunk
7980 nchunks + 1 ,
8081 ) ?
81- . to_primitive ( )
82- . buffer :: < u64 > ( ) ;
82+ . to_primitive ( ) ;
83+
84+ let chunk_offsets_buf = chunk_offsets_array. buffer :: < u64 > ( ) ;
8385
8486 // The remaining children contain the actual data of the chunks
85- let chunks = chunk_offsets
87+ let chunks = chunk_offsets_buf
8688 . iter ( )
8789 . tuple_windows ( )
8890 . enumerate ( )
@@ -93,9 +95,22 @@ impl VTable for ChunkedVTable {
9395 } )
9496 . try_collect ( ) ?;
9597
96- // SAFETY: All chunks are deserialized with the same dtype that was serialized.
97- // Each chunk was validated during deserialization to match the expected dtype.
98- unsafe { Ok ( ChunkedArray :: new_unchecked ( chunks, dtype. clone ( ) ) ) }
98+ let chunk_offsets = PrimitiveArray :: new ( chunk_offsets_buf. clone ( ) , Validity :: NonNullable ) ;
99+
100+ let total_len = chunk_offsets_buf
101+ . last ( )
102+ . ok_or_else ( || vortex_err ! ( "chunk_offsets must not be empty" ) ) ?;
103+ let len = usize:: try_from ( * total_len)
104+ . map_err ( |_| vortex_err ! ( "total length {} exceeds usize range" , total_len) ) ?;
105+
106+ // Construct directly using the struct fields to avoid recomputing chunk_offsets
107+ Ok ( ChunkedArray {
108+ dtype : dtype. clone ( ) ,
109+ len,
110+ chunk_offsets,
111+ chunks,
112+ stats_set : Default :: default ( ) ,
113+ } )
99114 }
100115
101116 fn execute ( array : & Self :: Array , ctx : & mut dyn ExecutionCtx ) -> VortexResult < Vector > {
0 commit comments