@@ -17,6 +17,7 @@ use vortex_array::ArrayView;
1717use vortex_array:: EqMode ;
1818use vortex_array:: ExecutionCtx ;
1919use vortex_array:: ExecutionResult ;
20+ use vortex_array:: ProbeState ;
2021use vortex_array:: TypedArrayRef ;
2122use vortex_array:: array_slots;
2223use vortex_array:: arrays:: Primitive ;
@@ -357,32 +358,44 @@ impl<T: TypedArrayRef<DecimalByteParts>> DecimalBytePartsArrayExt for T {}
357358impl OperationsVTable < DecimalByteParts > for DecimalByteParts {
358359 type ProbeState = ( ) ;
359360
360- fn scalar_at (
361- array : ArrayView < ' _ , DecimalByteParts > ,
361+ fn probe_scalar (
362+ state : & mut ProbeState < ' _ , DecimalByteParts > ,
362363 index : usize ,
363364 ctx : & mut ExecutionCtx ,
364365 ) -> VortexResult < Scalar > {
365- let scalar = array. msp ( ) . execute_scalar ( index, ctx) ?;
366+ let array = state. array ( ) ;
367+ let scalar = state
368+ . slot ( DecimalBytePartsSlots :: MSP ) ?
369+ . vortex_expect ( "validated DecimalByteParts MSP slot" )
370+ . execute_scalar ( index, ctx) ?;
371+ if scalar. is_null ( ) {
372+ return Ok ( Scalar :: null ( array. dtype ( ) . clone ( ) ) ) ;
373+ }
366374
367375 // Widen the MSP's signed value (i8/i16/i32/i64) to i64 for scalar reconstruction.
368376 // The array retains its original MSP storage type.
369377 let primitive_scalar = scalar. as_primitive ( ) ;
370378 let msp = primitive_scalar. as_ :: < i64 > ( ) . vortex_expect ( "non-null" ) ;
371379
372380 // Zero-extend each narrowed lower value to its 64-bit window.
373- let lower_parts = array
374- . lower_parts ( )
375- . iter ( )
376- . map ( |part| {
377- Ok ( part
378- . execute_scalar ( index, ctx) ?
379- . as_primitive ( )
380- . as_ :: < u64 > ( )
381- . vortex_expect ( "lower parts are non-nullable" ) )
382- } )
383- . collect :: < VortexResult < Vec < _ > > > ( ) ?;
381+ let lower_part_count = array. slots ( ) . len ( ) - DecimalBytePartsSlots :: LOWER_PARTS_OFFSET ;
382+ if lower_part_count > MAX_LOWER_PARTS {
383+ vortex_bail ! (
384+ "at most {MAX_LOWER_PARTS} lower parts are supported, got {lower_part_count}"
385+ ) ;
386+ }
387+ let mut lower_parts = [ 0u64 ; MAX_LOWER_PARTS ] ;
388+ for ( part_idx, lower_part) in lower_parts. iter_mut ( ) . take ( lower_part_count) . enumerate ( ) {
389+ * lower_part = state
390+ . slot ( DecimalBytePartsSlots :: LOWER_PARTS_OFFSET + part_idx) ?
391+ . vortex_expect ( "validated DecimalByteParts lower-part slot" )
392+ . execute_scalar ( index, ctx) ?
393+ . as_primitive ( )
394+ . as_ :: < u64 > ( )
395+ . vortex_expect ( "lower parts are non-nullable" ) ;
396+ }
384397
385- let value = match lower_parts. as_slice ( ) {
398+ let value = match & lower_parts[ ..lower_part_count ] {
386399 [ ] => DecimalValue :: I64 ( msp) ,
387400 [ first] => DecimalValue :: I128 ( assemble_wide_decimal_value ( msp, [ * first] ) ) ,
388401 [ first, second] => {
@@ -393,12 +406,20 @@ impl OperationsVTable<DecimalByteParts> for DecimalByteParts {
393406 }
394407 _ => vortex_bail ! (
395408 "at most {MAX_LOWER_PARTS} lower parts are supported, got {}" ,
396- lower_parts . len ( )
409+ lower_part_count
397410 ) ,
398411 } ;
399412
400413 Scalar :: try_new ( array. dtype ( ) . clone ( ) , Some ( ScalarValue :: Decimal ( value) ) )
401414 }
415+
416+ fn scalar_at (
417+ array : ArrayView < ' _ , DecimalByteParts > ,
418+ index : usize ,
419+ ctx : & mut ExecutionCtx ,
420+ ) -> VortexResult < Scalar > {
421+ Self :: probe_scalar ( & mut ProbeState :: once ( array) , index, ctx)
422+ }
402423}
403424
404425impl ValidityChild < DecimalByteParts > for DecimalByteParts {
0 commit comments