use crate::error::DrizzleError;
use crate::prelude::format;
pub fn checked_float_to_int<T>(value: f64, type_name: &str) -> Result<T, DrizzleError>
where
T: TryFrom<i128>,
<T as TryFrom<i128>>::Error: core::fmt::Display,
{
if !value.is_finite() {
return Err(DrizzleError::ConversionError(
format!("cannot convert non-finite float {value} to {type_name}").into(),
));
}
if value % 1.0 != 0.0 {
return Err(DrizzleError::ConversionError(
format!("cannot convert non-integer float {value} to {type_name}").into(),
));
}
const TWO_POW_127: f64 = f64::from_bits(0x47E0_0000_0000_0000);
let two_pow_127 = TWO_POW_127;
if value < -two_pow_127 || value >= two_pow_127 {
return Err(DrizzleError::ConversionError(
format!("float {value} out of range for {type_name}").into(),
));
}
let int_value: i128 = format!("{value:.0}").parse().map_err(|e| {
DrizzleError::ConversionError(
format!("float {value} could not be parsed as integer for {type_name}: {e}").into(),
)
})?;
int_value.try_into().map_err(|e| {
DrizzleError::ConversionError(
format!("float {value} out of range for {type_name}: {e}").into(),
)
})
}