From a18b2702caf4935f759cb07b8160004206e045c1 Mon Sep 17 00:00:00 2001 From: Chris Gillespie <6572184+gillespiecd@users.noreply.github.com> Date: Tue, 6 Oct 2020 10:30:18 -0700 Subject: [PATCH] Parse integers as BigInt (#2642) * Parse integer shape as BigInt * Use implicit serde from BigInt crate --- crates/nu-parser/src/parse.rs | 20 +++++++++++---- crates/nu-protocol/src/hir.rs | 4 +-- crates/nu-protocol/src/value.rs | 1 - crates/nu-protocol/src/value/primitive.rs | 4 +-- crates/nu-protocol/src/value/serde_bigint.rs | 26 -------------------- 5 files changed, 18 insertions(+), 37 deletions(-) delete mode 100644 crates/nu-protocol/src/value/serde_bigint.rs diff --git a/crates/nu-parser/src/parse.rs b/crates/nu-parser/src/parse.rs index 2e35f89c9..0a5d1928c 100644 --- a/crates/nu-parser/src/parse.rs +++ b/crates/nu-parser/src/parse.rs @@ -735,7 +735,7 @@ fn parse_arg( match expected_type { SyntaxShape::Number => { - if let Ok(x) = lite_arg.item.parse::() { + if let Ok(x) = lite_arg.item.parse::() { ( SpannedExpression::new(Expression::integer(x), lite_arg.span), None, @@ -757,7 +757,7 @@ fn parse_arg( } } SyntaxShape::Int => { - if let Ok(x) = lite_arg.item.parse::() { + if let Ok(x) = lite_arg.item.parse::() { ( SpannedExpression::new(Expression::integer(x), lite_arg.span), None, @@ -945,7 +945,7 @@ mod test { let registry = MockRegistry::new(); let result = parse_arg(SyntaxShape::Int, ®istry, &input); assert_eq!(result.1, None); - assert_eq!(result.0.expr, Expression::integer(32)); + assert_eq!(result.0.expr, Expression::integer(BigInt::from(32))); Ok(()) } @@ -970,14 +970,24 @@ mod test { let registry = MockRegistry::new(); let result = parse_arg(SyntaxShape::Number, ®istry, &input); assert_eq!(result.1, None); - assert_eq!(result.0.expr, Expression::integer(-34)); + assert_eq!(result.0.expr, Expression::integer(BigInt::from(-34))); let raw = "34".to_string(); let input = raw.clone().spanned(Span::new(0, raw.len())); let registry = MockRegistry::new(); let result = parse_arg(SyntaxShape::Number, ®istry, &input); assert_eq!(result.1, None); - assert_eq!(result.0.expr, Expression::integer(34)); + assert_eq!(result.0.expr, Expression::integer(BigInt::from(34))); + + let raw = "36893488147419103232".to_string(); + let input = raw.clone().spanned(Span::new(0, raw.len())); + let registry = MockRegistry::new(); + let result = parse_arg(SyntaxShape::Number, ®istry, &input); + assert_eq!(result.1, None); + assert_eq!( + result.0.expr, + Expression::integer(BigInt::from(36893488147419103232 as u128)) + ); Ok(()) } } diff --git a/crates/nu-protocol/src/hir.rs b/crates/nu-protocol/src/hir.rs index 9b72af37c..0480eca57 100644 --- a/crates/nu-protocol/src/hir.rs +++ b/crates/nu-protocol/src/hir.rs @@ -1095,8 +1095,8 @@ impl IntoSpanned for Expression { } impl Expression { - pub fn integer(i: i64) -> Expression { - Expression::Literal(Literal::Number(Number::Int(BigInt::from(i)))) + pub fn integer(i: BigInt) -> Expression { + Expression::Literal(Literal::Number(Number::Int(i))) } pub fn decimal(f: f64) -> Result { diff --git a/crates/nu-protocol/src/value.rs b/crates/nu-protocol/src/value.rs index bb9ef173c..669e7bfd4 100644 --- a/crates/nu-protocol/src/value.rs +++ b/crates/nu-protocol/src/value.rs @@ -8,7 +8,6 @@ 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 607319e66..bb74bcaba 100644 --- a/crates/nu-protocol/src/value/primitive.rs +++ b/crates/nu-protocol/src/value/primitive.rs @@ -1,7 +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 crate::value::serde_bigdecimal; use bigdecimal::BigDecimal; use chrono::{DateTime, Utc}; use nu_errors::{ExpectedRange, ShellError}; @@ -25,7 +25,6 @@ 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")] @@ -45,7 +44,6 @@ 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_bigint.rs b/crates/nu-protocol/src/value/serde_bigint.rs deleted file mode 100644 index c9c05bd57..000000000 --- a/crates/nu-protocol/src/value/serde_bigint.rs +++ /dev/null @@ -1,26 +0,0 @@ -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"))?) -}