@@ -169,21 +169,27 @@ pub fn decompress_chunked(
169169 let exponents = array. exponents ( ) ;
170170 let patches_offset = patches. offset ( ) ;
171171
172- // We need to drop ALPArray here in case converting encoded buffer into primitive didn't create a copy. In that case
173- // both alp_encoded and array will hold a reference to the buffer we want to mutate.
172+ // We need to drop ALPArray here in case converting encoded buffer into
173+ // primitive didn't create a copy. In that case both alp_encoded and array
174+ // will hold a reference to the buffer we want to mutate.
174175 drop ( array) ;
175176
176177 match_each_alp_float_ptype ! ( ptype, |T | {
177178 let patches_values = patches_values. as_slice:: <T >( ) ;
178179 let mut alp_buffer = encoded. into_buffer_mut( ) ;
179180 match_each_unsigned_integer_ptype!( patches_chunk_offsets. ptype( ) , |C | {
180181 let patches_chunk_offsets = patches_chunk_offsets. as_slice:: <C >( ) ;
182+ // There always is at least one chunk offset.
183+ let base_offset = patches_chunk_offsets[ 0 ] ;
184+ let offset_within_chunk = patches. offset_within_chunk( ) . unwrap_or( 0 ) ;
185+
181186 match_each_unsigned_integer_ptype!( patches_indices. ptype( ) , |I | {
182187 let patches_indices = patches_indices. as_slice:: <I >( ) ;
183188
184189 for ( chunk_idx, chunk_start) in ( 0 ..array_len) . step_by( 1024 ) . enumerate( ) {
185190 let chunk_end = ( chunk_start + 1024 ) . min( array_len) ;
186191 let chunk_slice = & mut alp_buffer. as_mut_slice( ) [ chunk_start..chunk_end] ;
192+
187193 <T >:: decode_slice_inplace( chunk_slice, exponents) ;
188194
189195 let decoded_chunk: & mut [ T ] = unsafe { transmute( chunk_slice) } ;
@@ -194,6 +200,8 @@ pub fn decompress_chunked(
194200 patches_offset,
195201 patches_chunk_offsets,
196202 chunk_idx,
203+ base_offset as usize ,
204+ offset_within_chunk,
197205 ) ;
198206 }
199207
@@ -214,8 +222,9 @@ fn decompress_unchunked(array: ALPArray) -> PrimitiveArray {
214222 let exponents = array. exponents ( ) ;
215223 let ptype = array. dtype ( ) . as_ptype ( ) ;
216224
217- // We need to drop ALPArray here in case converting encoded buffer into primitive didn't create a copy. In that case
218- // both alp_encoded and array will hold a reference to the buffer we want to mutate.
225+ // We need to drop ALPArray here in case converting encoded buffer into
226+ // primitive didn't create a copy. In that case both alp_encoded and array
227+ // will hold a reference to the buffer we want to mutate.
219228 drop ( array) ;
220229
221230 let decoded = match_each_alp_float_ptype ! ( ptype, |T | {
@@ -503,6 +512,27 @@ mod tests {
503512 assert ! ( encoded. patches( ) . is_some( ) ) ;
504513 }
505514
515+ #[ test]
516+ fn test_slice_across_chunks_with_patches_roundtrip ( ) {
517+ let mut values = vec ! [ 1.0f64 ; 2048 ] ;
518+ values[ 100 ] = PI ;
519+ values[ 200 ] = E ;
520+ values[ 600 ] = 42.42 ;
521+ values[ 800 ] = 42.42 ;
522+ values[ 1000 ] = 42.42 ;
523+ values[ 1023 ] = 42.42 ;
524+
525+ let original = PrimitiveArray :: new ( Buffer :: from ( values) , Validity :: NonNullable ) ;
526+ let encoded = alp_encode ( & original, None ) . unwrap ( ) ;
527+
528+ let sliced_alp = encoded. slice ( 1023 ..1025 ) ;
529+ let decoded = sliced_alp. to_primitive ( ) ;
530+
531+ let expected_slice = original. slice ( 1023 ..1025 ) . to_primitive ( ) ;
532+ assert_eq ! ( expected_slice. as_slice:: <f64 >( ) , decoded. as_slice:: <f64 >( ) ) ;
533+ assert ! ( encoded. patches( ) . is_some( ) ) ;
534+ }
535+
506536 #[ test]
507537 fn test_slice_half_chunk_nullable_roundtrip ( ) {
508538 let values = ( 0 ..1024 )
0 commit comments