@@ -14,6 +14,7 @@ use vortex_error::VortexExpect;
1414use vortex_error:: VortexResult ;
1515use vortex_error:: vortex_bail;
1616use vortex_error:: vortex_ensure;
17+ use vortex_error:: vortex_err;
1718use vortex_error:: vortex_panic;
1819use vortex_session:: VortexSession ;
1920
@@ -65,10 +66,29 @@ impl ValidityChild<Patched> for Patched {
6566
6667#[ derive( Clone , prost:: Message ) ]
6768pub struct PatchedMetadata {
68- #[ prost( uint32, tag = "1" ) ]
69- pub ( crate ) offset : u32 ,
69+ /// Length of the `inner` child.
70+ ///
71+ /// This may not match the length of the wrapping PatchedArray, if for example
72+ /// in a filter or slice it may be sliced to the nearest chunk boundary.
73+ #[ prost( uint64, tag = "1" ) ]
74+ pub ( crate ) inner_len : u64 ,
75+
76+ /// Offset within the first chunk of `inner` where data begins.
77+ ///
78+ /// This may become nonzero after slicing.
7079 #[ prost( uint32, tag = "2" ) ]
80+ pub ( crate ) offset : u32 ,
81+
82+ /// Number of patches. This is the length of the `indices` and `values` children.
83+ #[ prost( uint32, tag = "3" ) ]
7184 pub ( crate ) n_patches : u32 ,
85+
86+ /// Number of lanes the patches get spread over.
87+ ///
88+ /// By default, this is either 16 or 32 depending on the width of the type, but may change
89+ /// in the future, so we save it on write.
90+ #[ prost( uint32, tag = "4" ) ]
91+ pub ( crate ) n_lanes : u32 ,
7292}
7393
7494impl VTable for Patched {
@@ -158,8 +178,10 @@ impl VTable for Patched {
158178 #[ allow( clippy:: cast_possible_truncation) ]
159179 fn metadata ( array : & Self :: Array ) -> VortexResult < Self :: Metadata > {
160180 Ok ( ProstMetadata ( PatchedMetadata {
181+ inner_len : array. inner . len ( ) as u64 ,
161182 offset : array. offset as u32 ,
162183 n_patches : array. indices . len ( ) as u32 ,
184+ n_lanes : array. n_lanes as u32 ,
163185 } ) )
164186 }
165187
@@ -243,22 +265,32 @@ impl VTable for Patched {
243265 buffers : & [ BufferHandle ] ,
244266 children : & dyn ArrayChildren ,
245267 ) -> VortexResult < PatchedArray > {
246- let n_chunks = len. div_ceil ( 1024 ) ;
247- let n_lanes = match_each_native_ptype ! ( dtype. as_ptype( ) , |P | { patch_lanes:: <P >( ) } ) ;
268+ let inner_len = usize:: try_from ( metadata. inner_len ) . map_err ( |_| {
269+ vortex_err ! (
270+ "PatchedMetadata inner_len overflows usize: {}" ,
271+ metadata. inner_len
272+ )
273+ } ) ?;
274+ let offset = metadata. offset as usize ;
275+
276+ // n_chunks should correspond to the chunk in the `inner`.
277+ // After slicing when offset > 0, there may be additional chunks.
278+ let n_chunks = ( len + offset) . div_ceil ( 1024 ) ;
279+ let n_lanes = metadata. n_lanes as usize ;
248280
249281 let & [ lane_offsets] = & buffers else {
250282 vortex_bail ! ( "invalid buffer count for PatchedArray" ) ;
251283 } ;
252284
253- let inner = children. get ( 0 , dtype, len ) ?;
285+ let inner = children. get ( 0 , dtype, inner_len ) ?;
254286 let indices = children. get ( 1 , PType :: U16 . into ( ) , metadata. n_patches as usize ) ?;
255287 let values = children. get ( 2 , dtype, metadata. n_patches as usize ) ?;
256288
257289 Ok ( PatchedArray {
258290 inner,
259291 n_chunks,
260292 n_lanes,
261- offset : metadata . offset as usize ,
293+ offset,
262294 len,
263295 lane_offsets : lane_offsets. clone ( ) ,
264296 indices,
0 commit comments