Skip to content

Commit 49e72cd

Browse files
committed
Rename f_fallible and add docs
1 parent 5900bd4 commit 49e72cd

File tree

1 file changed

+24
-13
lines changed

1 file changed

+24
-13
lines changed

arrow-cast/src/cast/decimal.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
292301
pub 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

Comments
 (0)