diff --git a/crates/nu-protocol/src/value.rs b/crates/nu-protocol/src/value.rs index 28fcdf1b0a..6b45250a00 100644 --- a/crates/nu-protocol/src/value.rs +++ b/crates/nu-protocol/src/value.rs @@ -202,13 +202,22 @@ impl UntaggedValue { pub fn decimal_from_float(f: f64, span: Span) -> UntaggedValue { let dec = BigDecimal::from_f64(f); - match dec { - Some(dec) => UntaggedValue::Primitive(Primitive::Decimal(dec)), - None => UntaggedValue::Error(ShellError::labeled_error( - "Can not convert f64 to big decimal", - "can not create decimal", - span, - )), + // BigDecimal doesn't have the concept of inf/NaN so handle manually + if f.is_sign_negative() && f.is_infinite() { + UntaggedValue::from("-inf") + } else if f.is_infinite() { + UntaggedValue::from("inf") + } else if f.is_nan() { + UntaggedValue::from("NaN") + } else { + match dec { + Some(dec) => UntaggedValue::Primitive(Primitive::Decimal(dec)), + None => UntaggedValue::Error(ShellError::labeled_error( + "Can not convert f64 to big decimal", + "can not create decimal", + span, + )), + } } } @@ -550,3 +559,28 @@ pub fn merge_descriptors(values: &[Value]) -> Vec { } ret } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_decimal_from_float() { + assert_eq!( + UntaggedValue::from("inf"), + UntaggedValue::decimal_from_float(f64::INFINITY, Span::default()) + ); + assert_eq!( + UntaggedValue::from("-inf"), + UntaggedValue::decimal_from_float(f64::NEG_INFINITY, Span::default()) + ); + assert_eq!( + UntaggedValue::from("NaN"), + UntaggedValue::decimal_from_float(f64::NAN, Span::default()) + ); + assert_eq!( + UntaggedValue::from(5.5), + UntaggedValue::decimal_from_float(5.5, Span::default()) + ) + } +}