@@ -148,6 +148,11 @@ impl DecimalCast for i256 {
148148/// Construct closures to upscale decimals from `(input_precision, input_scale)` to
149149/// `(output_precision, output_scale)`.
150150///
151+ /// Returns `(f_fallible, f_infallible)` where:
152+ /// * `f_fallible` yields `None` when the requested cast would overflow
153+ /// * `f_infallible` is present only when every input is guaranteed to succeed; otherwise it is `None`
154+ /// and callers must fall back to `f_fallible`
155+ ///
151156/// Returns `None` if the required scale increase `delta_scale = output_scale - input_scale`
152157/// exceeds the supported precomputed precision table `O::MAX_FOR_EACH_PRECISION`.
153158/// In that case, the caller should treat this as an overflow for the output scale
@@ -174,7 +179,7 @@ where
174179 // handling, which is faster and simpler for scaling by 10^delta_scale.
175180 let max = O :: MAX_FOR_EACH_PRECISION . get ( delta_scale as usize ) ?;
176181 let mul = max. add_wrapping ( O :: Native :: ONE ) ;
177- let f = move |x| O :: Native :: from_decimal ( x) . and_then ( |x| x. mul_checked ( mul) . ok ( ) ) ;
182+ let f_fallible = move |x| O :: Native :: from_decimal ( x) . and_then ( |x| x. mul_checked ( mul) . ok ( ) ) ;
178183
179184 // if the gain in precision (digits) is greater than the multiplication due to scaling
180185 // every number will fit into the output type
@@ -185,12 +190,17 @@ where
185190 let is_infallible_cast = ( input_precision as i8 ) + delta_scale <= ( output_precision as i8 ) ;
186191 let f_infallible = is_infallible_cast
187192 . then_some ( move |x| O :: Native :: from_decimal ( x) . unwrap ( ) . mul_wrapping ( mul) ) ;
188- Some ( ( f , f_infallible) )
193+ Some ( ( f_fallible , f_infallible) )
189194}
190195
191196/// Construct closures to downscale decimals from `(input_precision, input_scale)` to
192197/// `(output_precision, output_scale)`.
193198///
199+ /// Returns `(f_fallible, f_infallible)` where:
200+ /// * `f_fallible` yields `None` when the requested cast would overflow
201+ /// * `f_infallible` is present only when every input is guaranteed to succeed; otherwise it is `None`
202+ /// and callers must fall back to `f_fallible`
203+ ///
194204/// Returns `None` if the required scale reduction `delta_scale = input_scale - output_scale`
195205/// exceeds the supported precomputed precision table `I::MAX_FOR_EACH_PRECISION`.
196206/// In this scenario, any value would round to zero (e.g., dividing by 10^k where k exceeds the
@@ -224,7 +234,7 @@ where
224234 let half = div. div_wrapping ( I :: Native :: ONE . add_wrapping ( I :: Native :: ONE ) ) ;
225235 let half_neg = half. neg_wrapping ( ) ;
226236
227- let f = move |x : I :: Native | {
237+ let f_fallible = move |x : I :: Native | {
228238 // div is >= 10 and so this cannot overflow
229239 let d = x. div_wrapping ( div) ;
230240 let r = x. mod_wrapping ( div) ;
@@ -249,8 +259,8 @@ where
249259 // e.g. Decimal(5, 3) 99.999 to Decimal(3, 0) will result in 100:
250260 // [99999] -> [99] + 1 = [100], a cast to Decimal(2, 0) would not be possible
251261 let is_infallible_cast = ( input_precision as i8 ) - delta_scale < ( output_precision as i8 ) ;
252- let f_infallible = is_infallible_cast. then_some ( move |x| f ( x) . unwrap ( ) ) ;
253- Some ( ( f , f_infallible) )
262+ let f_infallible = is_infallible_cast. then_some ( move |x| f_fallible ( x) . unwrap ( ) ) ;
263+ Some ( ( f_fallible , f_infallible) )
254264}
255265
256266/// Apply the rescaler function to the value.
@@ -284,9 +294,8 @@ where
284294/// is treated as an overflow for upscaling, or rounded to zero for downscaling (as any
285295/// possible result would be zero at the requested scale).
286296///
287- /// This mirrors the column-oriented helpers
288- /// [`convert_to_smaller_scale_decimal`] and [`convert_to_bigger_or_equal_scale_decimal`]
289- /// but operates on a single value (row-level) instead of an entire array.
297+ /// This mirrors the column-oriented helpers of decimal casting but operates on a single value
298+ /// (row-level) instead of an entire array.
290299///
291300/// Returns `None` if the value cannot be represented with the requested precision.
292301pub fn rescale_decimal < I : DecimalType , O : DecimalType > (
@@ -343,7 +352,7 @@ fn apply_decimal_cast<I: DecimalType, O: DecimalType>(
343352 array : & PrimitiveArray < I > ,
344353 output_precision : u8 ,
345354 output_scale : i8 ,
346- f : impl Fn ( I :: Native ) -> Option < O :: Native > ,
355+ f_fallible : impl Fn ( I :: Native ) -> Option < O :: Native > ,
347356 f_infallible : Option < impl Fn ( I :: Native ) -> O :: Native > ,
348357 cast_options : & CastOptions ,
349358) -> Result < PrimitiveArray < O > , ArrowError >
@@ -354,11 +363,13 @@ where
354363 let array = if let Some ( f_infallible) = f_infallible {
355364 array. unary ( f_infallible)
356365 } else if cast_options. safe {
357- array. unary_opt ( |x| f ( x) . filter ( |v| O :: is_valid_decimal_precision ( * v, output_precision) ) )
366+ array. unary_opt ( |x| {
367+ f_fallible ( x) . filter ( |v| O :: is_valid_decimal_precision ( * v, output_precision) )
368+ } )
358369 } else {
359370 let error = cast_decimal_to_decimal_error :: < I , O > ( output_precision, output_scale) ;
360371 array. try_unary ( |x| {
361- f ( x) . ok_or_else ( || error ( x) ) . and_then ( |v| {
372+ f_fallible ( x) . ok_or_else ( || error ( x) ) . and_then ( |v| {
362373 O :: validate_decimal_precision ( v, output_precision, output_scale) . map ( |_| v)
363374 } )
364375 } ) ?
@@ -380,14 +391,14 @@ where
380391 I :: Native : DecimalCast + ArrowNativeTypeOp ,
381392 O :: Native : DecimalCast + ArrowNativeTypeOp ,
382393{
383- if let Some ( ( f , f_infallible) ) =
394+ if let Some ( ( f_fallible , f_infallible) ) =
384395 make_downscaler :: < I , O > ( input_precision, input_scale, output_precision, output_scale)
385396 {
386397 apply_decimal_cast (
387398 array,
388399 output_precision,
389400 output_scale,
390- f ,
401+ f_fallible ,
391402 f_infallible,
392403 cast_options,
393404 )
0 commit comments