diff --git a/crates/nu-protocol/src/value.rs b/crates/nu-protocol/src/value.rs index 6b45250a0..de4a52c62 100644 --- a/crates/nu-protocol/src/value.rs +++ b/crates/nu-protocol/src/value.rs @@ -7,6 +7,8 @@ pub mod evaluate; pub mod iter; pub mod primitive; pub mod range; +mod serde_bigdecimal; +mod serde_bigint; use crate::hir; use crate::type_name::{ShellTypeName, SpannedTypeName}; diff --git a/crates/nu-protocol/src/value/primitive.rs b/crates/nu-protocol/src/value/primitive.rs index ebfb4bb27..607319e66 100644 --- a/crates/nu-protocol/src/value/primitive.rs +++ b/crates/nu-protocol/src/value/primitive.rs @@ -1,6 +1,7 @@ use crate::type_name::ShellTypeName; use crate::value::column_path::ColumnPath; use crate::value::range::{Range, RangeInclusion}; +use crate::value::{serde_bigdecimal, serde_bigint}; use bigdecimal::BigDecimal; use chrono::{DateTime, Utc}; use nu_errors::{ExpectedRange, ShellError}; @@ -24,8 +25,10 @@ pub enum Primitive { /// An empty value Nothing, /// A "big int", an integer with arbitrarily large size (aka not limited to 64-bit) + #[serde(with = "serde_bigint")] Int(BigInt), /// A "big decimal", an decimal number with arbitrarily large size (aka not limited to 64-bit) + #[serde(with = "serde_bigdecimal")] Decimal(BigDecimal), /// A count in the number of bytes, used as a filesize Filesize(u64), @@ -42,6 +45,7 @@ pub enum Primitive { /// A date value, in UTC Date(DateTime), /// A count in the number of nanoseconds + #[serde(with = "serde_bigint")] Duration(BigInt), /// A range of values Range(Box), diff --git a/crates/nu-protocol/src/value/serde_bigdecimal.rs b/crates/nu-protocol/src/value/serde_bigdecimal.rs new file mode 100644 index 000000000..0bc407f23 --- /dev/null +++ b/crates/nu-protocol/src/value/serde_bigdecimal.rs @@ -0,0 +1,26 @@ +use bigdecimal::BigDecimal; +use num_traits::cast::FromPrimitive; +use num_traits::cast::ToPrimitive; + +/// Enable big decimal serialization by providing a `serialize` function +pub fn serialize(big_decimal: &BigDecimal, serializer: S) -> Result +where + S: serde::Serializer, +{ + serde::Serialize::serialize( + &big_decimal + .to_f64() + .ok_or_else(|| serde::ser::Error::custom("expected a f64-sized bignum"))?, + serializer, + ) +} + +/// Enable big decimal deserialization by providing a `deserialize` function +pub fn deserialize<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let x: f64 = serde::Deserialize::deserialize(deserializer)?; + Ok(BigDecimal::from_f64(x) + .ok_or_else(|| serde::de::Error::custom("expected a f64-sized bigdecimal"))?) +} diff --git a/crates/nu-protocol/src/value/serde_bigint.rs b/crates/nu-protocol/src/value/serde_bigint.rs new file mode 100644 index 000000000..c9c05bd57 --- /dev/null +++ b/crates/nu-protocol/src/value/serde_bigint.rs @@ -0,0 +1,26 @@ +use num_bigint::BigInt; +use num_traits::cast::FromPrimitive; +use num_traits::cast::ToPrimitive; + +/// Enable big int serialization by providing a `serialize` function +pub fn serialize(big_int: &BigInt, serializer: S) -> Result +where + S: serde::Serializer, +{ + serde::Serialize::serialize( + &big_int + .to_i64() + .ok_or_else(|| serde::ser::Error::custom("expected a i64-sized bignum"))?, + serializer, + ) +} + +/// Enable big int deserialization by providing a `deserialize` function +pub fn deserialize<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let x: i64 = serde::Deserialize::deserialize(deserializer)?; + Ok(BigInt::from_i64(x) + .ok_or_else(|| serde::de::Error::custom("expected a i64-sized bignum"))?) +} diff --git a/wix/main.wxs b/wix/main.wxs index 00a20f0a9..f71f9b6ab 100644 --- a/wix/main.wxs +++ b/wix/main.wxs @@ -234,7 +234,7 @@ +