Update bigint/bigdecimal (#2585)

* Update bigint/bigdecimal

* clippy
This commit is contained in:
Jonathan Turner 2020-09-22 05:28:31 +12:00 committed by GitHub
parent 7a595827f1
commit 9b577b8679
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 263 additions and 132 deletions

48
Cargo.lock generated
View File

@ -359,11 +359,11 @@ dependencies = [
[[package]]
name = "bigdecimal"
version = "0.1.2"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1374191e2dd25f9ae02e3aa95041ed5d747fc77b3c102b49fe2dd9a8117a6244"
checksum = "cc403c26e6b03005522e6e8053384c4e881dfe5b2bf041c0c2c49be33d64a539"
dependencies = [
"num-bigint",
"num-bigint 0.3.0",
"num-integer",
"num-traits 0.2.12",
"serde 1.0.115",
@ -2378,9 +2378,9 @@ dependencies = [
[[package]]
name = "libsqlite3-sys"
version = "0.18.0"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e704a02bcaecd4a08b93a23f6be59d0bd79cd161e0963e9499165a0a35df7bd"
checksum = "e3a245984b1b06c291f46e27ebda9f369a94a1ab8461d0e845e23f9ced01f5db"
dependencies = [
"cc",
"pkg-config",
@ -2934,7 +2934,7 @@ dependencies = [
"nu-table",
"nu-test-support",
"nu-value-ext",
"num-bigint",
"num-bigint 0.3.0",
"num-format",
"num-traits 0.2.12",
"parking_lot 0.11.0",
@ -2997,7 +2997,7 @@ dependencies = [
"nu-source",
"nu-table",
"nu-value-ext",
"num-bigint",
"num-bigint 0.3.0",
"num-traits 0.2.12",
"parking_lot 0.11.0",
"query_interface",
@ -3017,7 +3017,7 @@ dependencies = [
"getset",
"glob",
"nu-source",
"num-bigint",
"num-bigint 0.3.0",
"num-traits 0.2.12",
"serde 1.0.115",
"serde_json",
@ -3037,7 +3037,7 @@ dependencies = [
"nu-errors",
"nu-protocol",
"nu-source",
"num-bigint",
"num-bigint 0.3.0",
"num-traits 0.2.12",
"serde 1.0.115",
"shellexpand",
@ -3053,7 +3053,7 @@ dependencies = [
"nu-protocol",
"nu-source",
"nu-value-ext",
"num-bigint",
"num-bigint 0.3.0",
"serde 1.0.115",
"serde_json",
]
@ -3075,7 +3075,7 @@ dependencies = [
"natural",
"nu-errors",
"nu-source",
"num-bigint",
"num-bigint 0.3.0",
"num-integer",
"num-traits 0.2.12",
"serde 1.0.115",
@ -3238,7 +3238,7 @@ dependencies = [
"nu-plugin",
"nu-protocol",
"nu-source",
"num-bigint",
"num-bigint 0.3.0",
]
[[package]]
@ -3278,7 +3278,7 @@ dependencies = [
"nu-plugin",
"nu-protocol",
"nu-source",
"num-bigint",
"num-bigint 0.3.0",
]
[[package]]
@ -3342,7 +3342,7 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
dependencies = [
"num-bigint",
"num-bigint 0.2.6",
"num-complex",
"num-integer",
"num-iter",
@ -3355,6 +3355,17 @@ name = "num-bigint"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
dependencies = [
"autocfg 1.0.1",
"num-integer",
"num-traits 0.2.12",
]
[[package]]
name = "num-bigint"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0"
dependencies = [
"autocfg 1.0.1",
"num-integer",
@ -3380,7 +3391,7 @@ checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465"
dependencies = [
"arrayvec 0.4.12",
"itoa",
"num-bigint",
"num-bigint 0.2.6",
]
[[package]]
@ -3411,7 +3422,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
dependencies = [
"autocfg 1.0.1",
"num-bigint",
"num-bigint 0.2.6",
"num-integer",
"num-traits 0.2.12",
]
@ -4395,9 +4406,9 @@ dependencies = [
[[package]]
name = "rusqlite"
version = "0.23.1"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45d0fd62e1df63d254714e6cb40d0a0e82e7a1623e7a27f679d851af092ae58b"
checksum = "4c78c3275d9d6eb684d2db4b2388546b32fdae0586c20a82f3905d21ea78b9ef"
dependencies = [
"bitflags",
"fallible-iterator",
@ -4406,7 +4417,6 @@ dependencies = [
"lru-cache",
"memchr",
"smallvec 1.4.2",
"time",
]
[[package]]

View File

@ -24,7 +24,7 @@ ansi_term = "0.12.1"
async-recursion = "0.3.1"
async-trait = "0.1.40"
base64 = "0.12.3"
bigdecimal = {version = "0.1.2", features = ["serde"]}
bigdecimal = {version = "0.2.0", features = ["serde"]}
byte-unit = "4.0.9"
bytes = "0.5.6"
calamine = "0.16.1"
@ -47,7 +47,7 @@ futures_codec = "0.4.1"
getset = "0.1.1"
git2 = {version = "0.13.11", default_features = false, optional = true}
glob = "0.3.0"
heim = {version = "0.1.0-beta.3", optional = true }
heim = {version = "0.1.0-beta.3", optional = true}
htmlescape = "0.3.1"
ical = "0.6.0"
ichwh = {version = "0.3.4", optional = true}
@ -56,7 +56,7 @@ itertools = "0.9.0"
log = "0.4.11"
meval = "0.2.0"
natural = "0.5.0"
num-bigint = {version = "0.2.6", features = ["serde"]}
num-bigint = {version = "0.3.0", features = ["serde"]}
num-format = {version = "0.4.0", features = ["with-num-bigint"]}
num-traits = "0.2.12"
parking_lot = "0.11.0"
@ -111,7 +111,7 @@ users = "0.10.0"
[dependencies.rusqlite]
features = ["bundled", "blob"]
optional = true
version = "0.23.1"
version = "0.24.0"
[build-dependencies]
git2 = {version = "0.13.11", optional = true}
@ -122,7 +122,7 @@ quickcheck_macros = "0.9.1"
[features]
clipboard-cli = ["clipboard"]
rich-benchmark = ["heim"]
rustyline-support = ["rustyline"]
stable = []
trash-support = ["trash"]
rich-benchmark = ["heim"]

View File

@ -14,6 +14,7 @@ fn from_delimited_string_to_value(
.delimiter(separator as u8)
.from_reader(s.as_bytes());
let tag = tag.into();
let span = tag.span;
let headers = if headerless {
(1..=reader.headers()?.len())
@ -30,7 +31,10 @@ fn from_delimited_string_to_value(
if let Ok(i) = value.parse::<i64>() {
tagged_row.insert_value(header, UntaggedValue::int(i).into_value(&tag))
} else if let Ok(f) = value.parse::<f64>() {
tagged_row.insert_value(header, UntaggedValue::decimal(f).into_value(&tag))
tagged_row.insert_value(
header,
UntaggedValue::decimal_from_float(f, span).into_value(&tag),
)
} else {
tagged_row.insert_value(header, UntaggedValue::string(value).into_value(&tag))
}

View File

@ -39,11 +39,12 @@ impl WholeStreamCommand for FromJSON {
fn convert_json_value_to_nu_value(v: &serde_hjson::Value, tag: impl Into<Tag>) -> Value {
let tag = tag.into();
let span = tag.span;
match v {
serde_hjson::Value::Null => UntaggedValue::Primitive(Primitive::Nothing).into_value(&tag),
serde_hjson::Value::Bool(b) => UntaggedValue::boolean(*b).into_value(&tag),
serde_hjson::Value::F64(n) => UntaggedValue::decimal(*n).into_value(&tag),
serde_hjson::Value::F64(n) => UntaggedValue::decimal_from_float(*n, span).into_value(&tag),
serde_hjson::Value::U64(n) => UntaggedValue::int(*n).into_value(&tag),
serde_hjson::Value::I64(n) => UntaggedValue::int(*n).into_value(&tag),
serde_hjson::Value::String(s) => {

View File

@ -45,6 +45,7 @@ async fn from_ods(
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let span = tag.span;
let registry = registry.clone();
let (
@ -73,7 +74,7 @@ async fn from_ods(
let value = match cell {
DataType::Empty => UntaggedValue::nothing(),
DataType::String(s) => UntaggedValue::string(s),
DataType::Float(f) => UntaggedValue::decimal(*f),
DataType::Float(f) => UntaggedValue::decimal_from_float(*f, span),
DataType::Int(i) => UntaggedValue::int(*i),
DataType::Bool(b) => UntaggedValue::boolean(*b),
_ => UntaggedValue::nothing(),

View File

@ -30,11 +30,12 @@ impl WholeStreamCommand for FromTOML {
pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> Value {
let tag = tag.into();
let span = tag.span;
match v {
toml::Value::Boolean(b) => UntaggedValue::boolean(*b).into_value(tag),
toml::Value::Integer(n) => UntaggedValue::int(*n).into_value(tag),
toml::Value::Float(n) => UntaggedValue::decimal(*n).into_value(tag),
toml::Value::Float(n) => UntaggedValue::decimal_from_float(*n, span).into_value(tag),
toml::Value::String(s) => {
UntaggedValue::Primitive(Primitive::String(String::from(s))).into_value(tag)
}

View File

@ -45,6 +45,7 @@ async fn from_xlsx(
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let tag = args.call_info.name_tag.clone();
let span = tag.span;
let registry = registry.clone();
let (
FromXLSXArgs {
@ -73,7 +74,7 @@ async fn from_xlsx(
let value = match cell {
DataType::Empty => UntaggedValue::nothing(),
DataType::String(s) => UntaggedValue::string(s),
DataType::Float(f) => UntaggedValue::decimal(*f),
DataType::Float(f) => UntaggedValue::decimal_from_float(*f, span),
DataType::Int(i) => UntaggedValue::int(*i),
DataType::Bool(b) => UntaggedValue::boolean(*b),
_ => UntaggedValue::nothing(),

View File

@ -58,6 +58,7 @@ fn convert_yaml_value_to_nu_value(
tag: impl Into<Tag>,
) -> Result<Value, ShellError> {
let tag = tag.into();
let span = tag.span;
let err_not_compatible_number = ShellError::labeled_error(
"Expected a compatible number",
@ -69,10 +70,11 @@ fn convert_yaml_value_to_nu_value(
serde_yaml::Value::Number(n) if n.is_i64() => {
UntaggedValue::int(n.as_i64().ok_or_else(|| err_not_compatible_number)?).into_value(tag)
}
serde_yaml::Value::Number(n) if n.is_f64() => {
UntaggedValue::decimal(n.as_f64().ok_or_else(|| err_not_compatible_number)?)
.into_value(tag)
}
serde_yaml::Value::Number(n) if n.is_f64() => UntaggedValue::decimal_from_float(
n.as_f64().ok_or_else(|| err_not_compatible_number)?,
span,
)
.into_value(tag),
serde_yaml::Value::String(s) => UntaggedValue::string(s).into_value(tag),
serde_yaml::Value::Sequence(a) => {
let result: Result<Vec<Value>, ShellError> = a

View File

@ -53,7 +53,11 @@ impl WholeStreamCommand for SubCommand {
vec![Example {
description: "Get the average of a list of numbers",
example: "echo [-50 100.0 25] | math avg",
result: Some(vec![UntaggedValue::decimal(25).into()]),
result: Some(vec![UntaggedValue::decimal_from_float(
25.0,
Span::unknown(),
)
.into()]),
}]
}
}

View File

@ -39,7 +39,7 @@ mod tests {
sum::summation, utils::calculate, utils::MathFunction, variance::variance,
};
use nu_plugin::row;
use nu_plugin::test_helpers::value::{decimal, int, table};
use nu_plugin::test_helpers::value::{decimal, decimal_from_float, int, table};
use nu_protocol::Value;
use std::str::FromStr;
@ -98,17 +98,17 @@ mod tests {
},
TestCase {
description: "Mixed Values",
values: vec![int(10), decimal(26.5), decimal(26.5)],
values: vec![int(10), decimal_from_float(26.5), decimal_from_float(26.5)],
expected_err: None,
expected_res: vec![
Ok(decimal(21)),
Ok(int(10)),
Ok(decimal(26.5)),
Ok(decimal(26.5)),
Ok(table(&[decimal(26.5)])),
Ok(decimal_from_float(26.5)),
Ok(decimal_from_float(26.5)),
Ok(table(&[decimal_from_float(26.5)])),
Ok(decimal(BigDecimal::from_str("7.77817459305202276840928798315333943213319531457321440247173855894902863154158871367713143880202865").expect("Could not convert to decimal from string"))),
Ok(decimal(63)),
Ok(decimal(60.5)),
Ok(decimal_from_float(60.5)),
],
},
TestCase {
@ -128,14 +128,14 @@ mod tests {
},
TestCase {
description: "Mixed Negative Values",
values: vec![decimal(-13.5), decimal(-11.5), int(10)],
values: vec![decimal_from_float(-13.5), decimal_from_float(-11.5), int(10)],
expected_err: None,
expected_res: vec![
Ok(decimal(-5)),
Ok(decimal(-13.5)),
Ok(decimal_from_float(-13.5)),
Ok(int(10)),
Ok(decimal(-11.5)),
Ok(table(&[decimal(-13.5), decimal(-11.5), int(10)])),
Ok(decimal_from_float(-11.5)),
Ok(table(&[decimal_from_float(-13.5), decimal_from_float(-11.5), int(10)])),
Ok(decimal(BigDecimal::from_str("10.63798226482196513098036125801342585449179971588207816421068645273754903468375890632981926875247027").expect("Could not convert to decimal from string"))),
Ok(decimal(-15)),
Ok(decimal(BigDecimal::from_str("113.1666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667").expect("Could not convert to decimal from string"))),
@ -151,10 +151,10 @@ mod tests {
],
expected_err: None,
expected_res: vec![
Ok(row!["col1".to_owned() => decimal(2.5), "col2".to_owned() => decimal(6.5)]),
Ok(row!["col1".to_owned() => decimal_from_float(2.5), "col2".to_owned() => decimal_from_float(6.5)]),
Ok(row!["col1".to_owned() => int(1), "col2".to_owned() => int(5)]),
Ok(row!["col1".to_owned() => int(4), "col2".to_owned() => int(8)]),
Ok(row!["col1".to_owned() => decimal(2.5), "col2".to_owned() => decimal(6.5)]),
Ok(row!["col1".to_owned() => decimal_from_float(2.5), "col2".to_owned() => decimal_from_float(6.5)]),
Ok(row![
"col1".to_owned() => table(&[int(1), int(2), int(3), int(4)]),
"col2".to_owned() => table(&[int(5), int(6), int(7), int(8)])
@ -164,7 +164,7 @@ mod tests {
"col2".to_owned() => decimal(BigDecimal::from_str("1.118033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137").expect("Could not convert to decimal from string"))
]),
Ok(row!["col1".to_owned() => int(10), "col2".to_owned() => int(26)]),
Ok(row!["col1".to_owned() => decimal(1.25), "col2".to_owned() => decimal(1.25)]),
Ok(row!["col1".to_owned() => decimal_from_float(1.25), "col2".to_owned() => decimal_from_float(1.25)]),
],
},
// TODO-Uncomment once Issue: https://github.com/nushell/nushell/issues/1883 is resolved

View File

@ -41,7 +41,11 @@ impl WholeStreamCommand for SubCommand {
vec![Example {
description: "Evalulate math in the pipeline",
example: "echo '10 / 4' | math eval",
result: Some(vec![UntaggedValue::decimal(2.5).into()]),
result: Some(vec![UntaggedValue::decimal_from_float(
2.5,
Span::unknown(),
)
.into()]),
}]
}
}

View File

@ -50,7 +50,11 @@ impl WholeStreamCommand for SubCommand {
vec![Example {
description: "Get the median of a list of numbers",
example: "echo [3 8 9 12 12 15] | math median",
result: Some(vec![UntaggedValue::decimal(10.5).into()]),
result: Some(vec![UntaggedValue::decimal_from_float(
10.5,
Span::unknown(),
)
.into()]),
}]
}
}

View File

@ -99,12 +99,20 @@ impl WholeStreamCommand for SubCommand {
Example {
description: "Get the variance of a list of numbers",
example: "echo [1 2 3 4 5] | math variance",
result: Some(vec![UntaggedValue::decimal(2).into()]),
result: Some(vec![UntaggedValue::decimal_from_float(
2.0,
Span::unknown(),
)
.into()]),
},
Example {
description: "Get the sample variance of a list of numbers",
example: "echo [1 2 3 4 5] | math variance -s",
result: Some(vec![UntaggedValue::decimal(2.5).into()]),
result: Some(vec![UntaggedValue::decimal_from_float(
2.5,
Span::unknown(),
)
.into()]),
},
]
}

View File

@ -8,7 +8,7 @@ use nu_source::Tagged;
use num_bigint::{BigInt, BigUint, ToBigInt};
// TODO num_format::SystemLocale once platform-specific dependencies are stable (see Cargo.toml)
use num_format::{Locale, ToFormattedString};
use num_format::Locale;
use num_traits::{Pow, Signed};
use std::iter;
@ -40,12 +40,15 @@ impl WholeStreamCommand for SubCommand {
"decimal digits to which to round",
Some('d'),
)
.switch(
"group-digits",
// TODO according to system localization
"group digits, currently by thousand with commas",
Some('g'),
)
/*
FIXME: this isn't currently supported because of num_format being out of date. Once it's updated, re-enable this
.switch(
"group-digits",
// TODO according to system localization
"group digits, currently by thousand with commas",
Some('g'),
)
*/
}
fn usage(&self) -> &str {
@ -67,6 +70,8 @@ impl WholeStreamCommand for SubCommand {
example: "= 1.7 | str from -d 0",
result: Some(vec![UntaggedValue::string("2").into_untagged_value()]),
},
/*
FIXME: this isn't currently supported because of num_format being out of date. Once it's updated, re-enable this
Example {
description: "format large number with localized digit grouping",
example: "= 1000000.2 | str from -g",
@ -74,6 +79,7 @@ impl WholeStreamCommand for SubCommand {
UntaggedValue::string("1,000,000.2").into_untagged_value()
]),
},
*/
]
}
}
@ -147,7 +153,7 @@ pub fn action(
}
fn format_bigint(int: &BigInt) -> String {
int.to_formatted_string(&Locale::en)
format!("{}", int)
// TODO once platform-specific dependencies are stable (see Cargo.toml)
// #[cfg(windows)]
@ -200,10 +206,8 @@ fn format_decimal(mut decimal: BigDecimal, digits: Option<u64>, group_digits: bo
let format_default_loc = |int_part: BigInt| {
let loc = Locale::en;
let (int_str, sep) = (
int_part.to_formatted_string(&loc),
String::from(loc.decimal()),
);
//TODO: when num_format is available for recent bigint, replace this with the locale-based format
let (int_str, sep) = (format!("{}", int_part), String::from(loc.decimal()));
format!("{}{}{}", int_str, sep, dec_str)
};

View File

@ -113,7 +113,7 @@ fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
#[cfg(test)]
mod tests {
use super::{action, SubCommand};
use nu_plugin::test_helpers::value::{decimal, string};
use nu_plugin::test_helpers::value::{decimal_from_float, string};
use nu_source::Tag;
#[test]
@ -127,7 +127,7 @@ mod tests {
#[allow(clippy::approx_constant)]
fn turns_to_integer() {
let word = string("3.1415");
let expected = decimal(3.1415);
let expected = decimal_from_float(3.1415);
let actual = action(&word, Tag::unknown()).unwrap();
assert_eq!(actual, expected);

View File

@ -11,21 +11,21 @@ doctest = false
[dependencies]
ansi_term = "0.12.1"
bigdecimal = "0.1.2"
bigdecimal = "0.2.0"
byte-unit = "4.0.9"
chrono = "0.4.15"
derive-new = "0.5.8"
directories = { version = "3.0.1", optional = true }
dirs = { version = "3.0.1", optional = true }
directories = {version = "3.0.1", optional = true}
dirs = {version = "3.0.1", optional = true}
getset = "0.1.1"
indexmap = { version = "1.6.0", features = ["serde-1"] }
indexmap = {version = "1.6.0", features = ["serde-1"]}
log = "0.4.11"
num-bigint = { version = "0.2.6", features = ["serde"] }
num-bigint = {version = "0.3.0", features = ["serde"]}
num-traits = "0.2.12"
parking_lot = "0.11.0"
query_interface = "0.3.5"
serde = { version = "1.0.115", features = ["derive"] }
serde = {version = "1.0.115", features = ["derive"]}
toml = "0.5.6"
nu-errors = {version = "0.19.0", path = "../nu-errors"}

View File

@ -24,7 +24,7 @@ pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> V
match v {
toml::Value::Boolean(b) => UntaggedValue::boolean(*b).into_value(tag),
toml::Value::Integer(n) => UntaggedValue::int(*n).into_value(tag),
toml::Value::Float(n) => UntaggedValue::decimal(*n).into_value(tag),
toml::Value::Float(n) => UntaggedValue::decimal_from_float(*n, tag.span).into_value(tag),
toml::Value::String(s) => {
UntaggedValue::Primitive(Primitive::String(String::from(s))).into_value(tag)
}

View File

@ -253,7 +253,7 @@ pub fn percentages(
&split
.table_entries()
.filter_map(|s| {
let hundred = UntaggedValue::decimal(100);
let hundred = UntaggedValue::decimal_from_float(100.0, tag.span);
match compute_values(Operator::Divide, &hundred, &maxima) {
Ok(v) => match compute_values(Operator::Multiply, &s, &v) {

View File

@ -103,7 +103,7 @@ pub mod helpers {
use indexmap::indexmap;
use nu_errors::ShellError;
use nu_protocol::{UntaggedValue, Value};
use nu_source::{Tag, TaggedItem};
use nu_source::{Span, Tag, TaggedItem};
use nu_value_ext::ValueExt;
use num_bigint::BigInt;
@ -117,6 +117,10 @@ pub mod helpers {
UntaggedValue::decimal(f.into()).into_untagged_value()
}
pub fn decimal_from_float(f: f64, span: Span) -> Value {
UntaggedValue::decimal_from_float(f, span).into_untagged_value()
}
pub fn string(input: impl Into<String>) -> Value {
UntaggedValue::string(input.into()).into_untagged_value()
}
@ -228,12 +232,13 @@ pub mod helpers {
#[cfg(test)]
mod tests {
use super::helpers::{
assert_without_checking_percentages, committers, date_formatter, decimal, int, table,
assert_without_checking_percentages, committers, date_formatter, decimal,
decimal_from_float, int, table,
};
use super::{report, Labels, Model, Operation, Range};
use nu_errors::ShellError;
use nu_protocol::Value;
use nu_source::{Tag, TaggedItem};
use nu_source::{Span, Tag, TaggedItem};
use nu_value_ext::ValueExt;
#[test]
fn prepares_report_using_accumulating_value() {
@ -299,9 +304,21 @@ mod tests {
table(&[int(2), int(6), int(12)]),
]),
percentages: table(&[
table(&[decimal(16.66), decimal(50), decimal(100)]),
table(&[decimal(8.33), decimal(25), decimal(50)]),
table(&[decimal(3.33), decimal(10), decimal(20)]),
table(&[
decimal_from_float(16.66, Span::unknown()),
decimal(50),
decimal(100),
]),
table(&[
decimal_from_float(8.33, Span::unknown()),
decimal(25),
decimal(50),
]),
table(&[
decimal_from_float(3.33, Span::unknown()),
decimal(10),
decimal(20),
]),
]),
},
);

View File

@ -13,13 +13,13 @@ doctest = false
nu-source = {path = "../nu-source", version = "0.19.0"}
ansi_term = "0.12.1"
bigdecimal = { version = "0.1.2", features = ["serde"] }
codespan-reporting = { version = "0.9.5", features = ["serialization"] }
bigdecimal = {version = "0.2.0", features = ["serde"]}
codespan-reporting = {version = "0.9.5", features = ["serialization"]}
derive-new = "0.5.8"
getset = "0.1.1"
num-bigint = { version = "0.2.6", features = ["serde"] }
num-bigint = {version = "0.3.0", features = ["serde"]}
num-traits = "0.2.12"
serde = { version = "1.0.115", features = ["derive"] }
serde = {version = "1.0.115", features = ["derive"]}
# implement conversions
glob = "0.3.0"

View File

@ -9,12 +9,12 @@ version = "0.19.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bigdecimal = { version = "0.1.2", features = ["serde"] }
bigdecimal = {version = "0.2.0", features = ["serde"]}
codespan-reporting = "0.9.5"
derive-new = "0.5.8"
indexmap = { version = "1.6.0", features = ["serde-1"] }
indexmap = {version = "1.6.0", features = ["serde-1"]}
log = "0.4.11"
num-bigint = { version = "0.2.6", features = ["serde"] }
num-bigint = {version = "0.3.0", features = ["serde"]}
num-traits = "0.2.12"
serde = "1.0.115"
shellexpand = "2.0.0"

View File

@ -741,10 +741,14 @@ fn parse_arg(
None,
)
} else if let Ok(x) = lite_arg.item.parse::<f64>() {
(
SpannedExpression::new(Expression::decimal(x), lite_arg.span),
None,
)
if let Ok(x) = Expression::decimal(x) {
(SpannedExpression::new(x, lite_arg.span), None)
} else {
(
garbage(lite_arg.span),
Some(ParseError::mismatch("number", lite_arg.clone())),
)
}
} else {
(
garbage(lite_arg.span),
@ -952,14 +956,14 @@ mod test {
let registry = MockRegistry::new();
let result = parse_arg(SyntaxShape::Number, &registry, &input);
assert_eq!(result.1, None);
assert_eq!(result.0.expr, Expression::decimal(-32.2));
assert_eq!(result.0.expr, Expression::decimal(-32.2)?);
let raw = "32.2".to_string();
let input = raw.clone().spanned(Span::new(0, raw.len()));
let registry = MockRegistry::new();
let result = parse_arg(SyntaxShape::Number, &registry, &input);
assert_eq!(result.1, None);
assert_eq!(result.0.expr, Expression::decimal(32.2));
assert_eq!(result.0.expr, Expression::decimal(32.2)?);
let raw = "-34".to_string();
let input = raw.clone().spanned(Span::new(0, raw.len()));

View File

@ -15,10 +15,10 @@ nu-protocol = {path = "../nu-protocol", version = "0.19.0"}
nu-source = {path = "../nu-source", version = "0.19.0"}
nu-value-ext = {path = "../nu-value-ext", version = "0.19.0"}
bigdecimal = { version = "0.1.2", features = ["serde"] }
indexmap = { version = "1.6.0", features = ["serde-1"] }
num-bigint = { version = "0.2.6", features = ["serde"] }
serde = { version = "1.0.115", features = ["derive"] }
bigdecimal = {version = "0.2.0", features = ["serde"]}
indexmap = {version = "1.6.0", features = ["serde-1"]}
num-bigint = {version = "0.3.0", features = ["serde"]}
serde = {version = "1.0.115", features = ["derive"]}
serde_json = "1.0.57"
[build-dependencies]

View File

@ -162,7 +162,7 @@ pub mod value {
use bigdecimal::BigDecimal;
use nu_errors::ShellError;
use nu_protocol::{Primitive, TaggedDictBuilder, UntaggedValue, Value};
use nu_source::Tag;
use nu_source::{Span, Tag};
use nu_value_ext::ValueExt;
use num_bigint::BigInt;
@ -175,7 +175,11 @@ pub mod value {
}
pub fn decimal(f: impl Into<BigDecimal>) -> Value {
UntaggedValue::Primitive(Primitive::Decimal(f.into())).into_untagged_value()
UntaggedValue::decimal(f.into()).into_untagged_value()
}
pub fn decimal_from_float(f: f64) -> Value {
UntaggedValue::decimal_from_float(f, Span::unknown()).into_untagged_value()
}
pub fn string(input: impl Into<String>) -> Value {

View File

@ -11,22 +11,22 @@ doctest = false
[dependencies]
ansi_term = "0.12.1"
bigdecimal = { version = "0.1.2", features = ["serde"] }
bigdecimal = {version = "0.2.0", features = ["serde"]}
byte-unit = "4.0.9"
chrono = { version = "0.4.15", features = ["serde"] }
chrono = {version = "0.4.15", features = ["serde"]}
codespan-reporting = "0.9.5"
derive-new = "0.5.8"
getset = "0.1.1"
indexmap = { version = "1.6.0", features = ["serde-1"] }
indexmap = {version = "1.6.0", features = ["serde-1"]}
itertools = "0.9.0"
log = "0.4.11"
natural = "0.5.0"
nu-errors = {path = "../nu-errors", version = "0.19.0"}
nu-source = {path = "../nu-source", version = "0.19.0"}
num-bigint = { version = "0.2.6", features = ["serde"] }
num-bigint = {version = "0.3.0", features = ["serde"]}
num-integer = "0.1.43"
num-traits = "0.2.12"
serde = { version = "1.0.115", features = ["derive"] }
serde = {version = "1.0.115", features = ["derive"]}
serde_bytes = "0.11.5"
# implement conversions

View File

@ -1099,8 +1099,18 @@ impl Expression {
Expression::Literal(Literal::Number(Number::Int(BigInt::from(i))))
}
pub fn decimal(f: f64) -> Expression {
Expression::Literal(Literal::Number(Number::Decimal(BigDecimal::from(f))))
pub fn decimal(f: f64) -> Result<Expression, ParseError> {
let dec = BigDecimal::from_f64(f);
let dec = match dec {
Some(x) => Ok(x),
None => Err(ParseError::internal_error(
"Can not convert f64 to big decimal"
.to_string()
.spanned_unknown(),
)),
}?;
Ok(Expression::Literal(Literal::Number(Number::Decimal(dec))))
}
pub fn string(s: String) -> Expression {

View File

@ -17,6 +17,7 @@ use crate::value::primitive::Primitive;
use crate::value::range::{Range, RangeInclusion};
use crate::{ColumnPath, PathMember, UnspannedPathMember};
use bigdecimal::BigDecimal;
use bigdecimal::FromPrimitive;
use chrono::{DateTime, Utc};
use indexmap::IndexMap;
use itertools::Itertools;
@ -190,8 +191,22 @@ impl UntaggedValue {
}
/// Helper for creating decimal values
pub fn decimal(s: impl Into<BigDecimal>) -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Decimal(s.into()))
pub fn decimal(s: BigDecimal) -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Decimal(s))
}
/// Helper for creating decimal values
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,
)),
}
}
/// Helper for creating binary (non-text) buffer values

View File

@ -10,8 +10,8 @@ version = "0.19.0"
doctest = false
[dependencies]
bigdecimal = "0.1.2"
bson = { version = "0.14.1", features = ["decimal128"] }
bigdecimal = "0.2.0"
bson = {version = "0.14.1", features = ["decimal128"]}
nu-errors = {path = "../nu-errors", version = "0.19.0"}
nu-plugin = {path = "../nu-plugin", version = "0.19.0"}
nu-protocol = {path = "../nu-protocol", version = "0.19.0"}

View File

@ -10,7 +10,7 @@ version = "0.19.0"
doctest = false
[dependencies]
bigdecimal = "0.1.2"
bigdecimal = "0.2.0"
nu-errors = {path = "../nu-errors", version = "0.19.0"}
nu-plugin = {path = "../nu-plugin", version = "0.19.0"}
nu-protocol = {path = "../nu-protocol", version = "0.19.0"}
@ -21,6 +21,6 @@ tempfile = "3.1.0"
[dependencies.rusqlite]
features = ["bundled", "blob"]
version = "0.23.1"
version = "0.24.0"
[build-dependencies]

View File

@ -1,3 +1,4 @@
use bigdecimal::FromPrimitive;
use nu_errors::ShellError;
use nu_protocol::{Primitive, ReturnSuccess, ReturnValue, TaggedDictBuilder, UntaggedValue, Value};
use nu_source::Tag;
@ -58,9 +59,9 @@ fn convert_sqlite_row_to_nu_value(
tag: impl Into<Tag> + Clone,
) -> Result<Value, rusqlite::Error> {
let mut collected = TaggedDictBuilder::new(tag.clone());
for (i, c) in row.columns().iter().enumerate() {
for (i, c) in row.column_names().iter().enumerate() {
collected.insert_value(
c.name().to_string(),
c.to_string(),
convert_sqlite_value_to_nu_value(row.get_raw(i), tag.clone()),
);
}
@ -73,7 +74,20 @@ fn convert_sqlite_value_to_nu_value(value: ValueRef, tag: impl Into<Tag> + Clone
UntaggedValue::Primitive(Primitive::String(String::from(""))).into_value(tag)
}
ValueRef::Integer(i) => UntaggedValue::int(i).into_value(tag),
ValueRef::Real(f) => UntaggedValue::decimal(f).into_value(tag),
ValueRef::Real(f) => {
let f = bigdecimal::BigDecimal::from_f64(f);
let tag = tag.into();
let span = tag.span;
match f {
Some(d) => UntaggedValue::decimal(d).into_value(tag),
None => UntaggedValue::Error(ShellError::labeled_error(
"Can not convert f64 to big decimal",
"can not convert to decimal",
span,
))
.into_value(tag),
}
}
ValueRef::Text(s) => {
// this unwrap is safe because we know the ValueRef is Text.
UntaggedValue::Primitive(Primitive::String(String::from_utf8_lossy(s).to_string()))

View File

@ -15,9 +15,9 @@ nu-plugin = {path = "../nu-plugin", version = "0.19.0"}
nu-protocol = {path = "../nu-protocol", version = "0.19.0"}
nu-source = {path = "../nu-source", version = "0.19.0"}
num-bigint = "0.2.6"
num-bigint = "0.3.0"
futures = { version = "0.3.5", features = ["compat", "io-compat"] }
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
futures-timer = "3.0.2"
[dependencies.heim]

View File

@ -60,7 +60,10 @@ pub async fn ps(tag: Tag, long: bool) -> Result<Vec<Value>, ShellError> {
if let Ok(status) = process.status().await {
dict.insert_untagged("status", UntaggedValue::string(format!("{:?}", status)));
}
dict.insert_untagged("cpu", UntaggedValue::decimal(usage.get::<ratio::percent>()));
dict.insert_untagged(
"cpu",
UntaggedValue::decimal_from_float(usage.get::<ratio::percent>() as f64, tag.span),
);
dict.insert_untagged(
"mem",
UntaggedValue::filesize(memory.rss().get::<information::byte>()),

View File

@ -16,9 +16,9 @@ nu-protocol = {path = "../nu-protocol", version = "0.19.0"}
nu-source = {path = "../nu-source", version = "0.19.0"}
battery = "0.7.6"
futures = { version = "0.3.5", features = ["compat", "io-compat"] }
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
futures-util = "0.3.5"
num-bigint = "0.2.6"
num-bigint = "0.3.0"
[dependencies.heim]
default-features = false

View File

@ -17,6 +17,7 @@ impl Sys {
}
async fn cpu(tag: Tag) -> Option<Value> {
let span = tag.span;
match futures::future::try_join(heim::cpu::logical_count(), heim::cpu::frequency()).await {
Ok((num_cpu, cpu_speed)) => {
let mut cpu_idx = TaggedDictBuilder::with_capacity(tag, 4);
@ -26,20 +27,29 @@ async fn cpu(tag: Tag) -> Option<Value> {
(cpu_speed.current().get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0)
.round()
/ 100.0;
cpu_idx.insert_untagged("current ghz", UntaggedValue::decimal(current_speed));
cpu_idx.insert_untagged(
"current ghz",
UntaggedValue::decimal_from_float(current_speed, span),
);
if let Some(min_speed) = cpu_speed.min() {
let min_speed =
(min_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round()
/ 100.0;
cpu_idx.insert_untagged("min ghz", UntaggedValue::decimal(min_speed));
cpu_idx.insert_untagged(
"min ghz",
UntaggedValue::decimal_from_float(min_speed, span),
);
}
if let Some(max_speed) = cpu_speed.max() {
let max_speed =
(max_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round()
/ 100.0;
cpu_idx.insert_untagged("max ghz", UntaggedValue::decimal(max_speed));
cpu_idx.insert_untagged(
"max ghz",
UntaggedValue::decimal_from_float(max_speed, span),
);
}
Some(cpu_idx.into_value())
@ -185,6 +195,7 @@ async fn disks(tag: Tag) -> Result<Option<UntaggedValue>, ShellError> {
async fn battery(tag: Tag) -> Option<UntaggedValue> {
let mut output = vec![];
let span = tag.span;
if let Ok(manager) = battery::Manager::new() {
if let Ok(batteries) = manager.batteries() {
@ -203,16 +214,18 @@ async fn battery(tag: Tag) -> Option<UntaggedValue> {
if let Some(time_to_full) = battery.time_to_full() {
dict.insert_untagged(
"mins to full",
UntaggedValue::decimal(
time_to_full.get::<battery::units::time::minute>(),
UntaggedValue::decimal_from_float(
time_to_full.get::<battery::units::time::minute>() as f64,
span,
),
);
}
if let Some(time_to_empty) = battery.time_to_empty() {
dict.insert_untagged(
"mins to empty",
UntaggedValue::decimal(
time_to_empty.get::<battery::units::time::minute>(),
UntaggedValue::decimal_from_float(
time_to_empty.get::<battery::units::time::minute>() as f64,
span,
),
);
}
@ -231,6 +244,7 @@ async fn battery(tag: Tag) -> Option<UntaggedValue> {
async fn temp(tag: Tag) -> Option<UntaggedValue> {
let mut output = vec![];
let span = tag.span;
let sensors = sensors::temperatures();
@ -245,23 +259,29 @@ async fn temp(tag: Tag) -> Option<UntaggedValue> {
}
dict.insert_untagged(
"temp",
UntaggedValue::decimal(
UntaggedValue::decimal_from_float(
sensor
.current()
.get::<thermodynamic_temperature::degree_celsius>(),
.get::<thermodynamic_temperature::degree_celsius>()
as f64,
span,
),
);
if let Some(high) = sensor.high() {
dict.insert_untagged(
"high",
UntaggedValue::decimal(high.get::<thermodynamic_temperature::degree_celsius>()),
UntaggedValue::decimal_from_float(
high.get::<thermodynamic_temperature::degree_celsius>() as f64,
span,
),
);
}
if let Some(critical) = sensor.critical() {
dict.insert_untagged(
"critical",
UntaggedValue::decimal(
critical.get::<thermodynamic_temperature::degree_celsius>(),
UntaggedValue::decimal_from_float(
critical.get::<thermodynamic_temperature::degree_celsius>() as f64,
span,
),
);
}

View File

@ -21,6 +21,6 @@ tempfile = "3.1.0"
[dependencies.rusqlite]
features = ["bundled", "blob"]
version = "0.23.1"
version = "0.24.0"
[build-dependencies]