nu-parser + nu-protocol: switch to metric for KB, MB, GB, add KiB, MiB, GiB units (#3035)

fixes inconsistency with formatting/rendering which uses standard Rust byte_unit
https://en.wikipedia.org/wiki/Byte#Multiple-byte_units
This commit is contained in:
Saeed Rasooli 2021-02-10 06:01:12 +03:30 committed by GitHub
parent 3443ca40c5
commit b403fb1275
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 128 additions and 17 deletions

View File

@ -31,11 +31,18 @@ impl WholeStreamCommand for IntoInt {
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Convert filesize to integer",
example: "into-int 1kb | each { = $it / 1024 }",
result: Some(vec![UntaggedValue::int(1).into()]),
}]
vec![
Example {
description: "Convert filesize to integer",
example: "into-int 1kb | each { = $it / 1000 }",
result: Some(vec![UntaggedValue::int(1).into()]),
},
Example {
description: "Convert filesize to integer",
example: "into-int 1kib | each { = $it / 1024 }",
result: Some(vec![UntaggedValue::int(1).into()]),
},
]
}
}

View File

@ -5,7 +5,19 @@ fn into_int_filesize() {
let actual = nu!(
cwd: ".", pipeline(
r#"
into-int 1kb | each {= $it / 1024 }
into-int 1kb | each {= $it / 1000 }
"#
));
assert!(actual.out.contains('1'));
}
#[test]
fn into_int_filesize2() {
let actual = nu!(
cwd: ".", pipeline(
r#"
into-int 1kib | each {= $it / 1024 }
"#
));

View File

@ -7,7 +7,7 @@ use nu_test_support::pipeline;
fn filters_by_unit_size_comparison() {
let actual = nu!(
cwd: "tests/fixtures/formats",
"ls | where size > 1kb | sort-by size | get name | first 1 | str trim"
"ls | where size > 1kib | sort-by size | get name | first 1 | str trim"
);
assert_eq!(actual.out, "cargo_sample.toml");

View File

@ -332,6 +332,9 @@ fn parse_unit(lite_arg: &Spanned<String>) -> (SpannedExpression, Option<ParseErr
(Unit::Gigabyte, vec!["gb", "GB", "Gb", "gB"]),
(Unit::Terabyte, vec!["tb", "TB", "Tb", "tB"]),
(Unit::Petabyte, vec!["pb", "PB", "Pb", "pB"]),
(Unit::Kibibyte, vec!["KiB", "kib", "kiB", "Kib"]),
(Unit::Mebibyte, vec!["MiB", "mib", "miB", "Mib"]),
(Unit::Gibibyte, vec!["GiB", "gib", "giB", "Gib"]),
(Unit::Nanosecond, vec!["ns"]),
(Unit::Microsecond, vec!["us"]),
(Unit::Millisecond, vec!["ms"]),
@ -2215,6 +2218,41 @@ fn unit_parse_byte_units() -> Result<(), ParseError> {
value: 27,
unit: Unit::Petabyte,
},
TestCase {
string: String::from("10kib"),
value: 10,
unit: Unit::Kibibyte,
},
TestCase {
string: String::from("123KiB"),
value: 123,
unit: Unit::Kibibyte,
},
TestCase {
string: String::from("24kiB"),
value: 24,
unit: Unit::Kibibyte,
},
TestCase {
string: String::from("10mib"),
value: 10,
unit: Unit::Mebibyte,
},
TestCase {
string: String::from("123MiB"),
value: 123,
unit: Unit::Mebibyte,
},
TestCase {
string: String::from("10gib"),
value: 10,
unit: Unit::Gibibyte,
},
TestCase {
string: String::from("123GiB"),
value: 123,
unit: Unit::Gibibyte,
},
];
for case in cases.iter() {

View File

@ -346,7 +346,7 @@ impl HasSpan for ExternalCommand {
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Copy, Deserialize, Serialize)]
pub enum Unit {
// Filesize units
// Filesize units: metric
Byte,
Kilobyte,
Megabyte,
@ -354,6 +354,11 @@ pub enum Unit {
Terabyte,
Petabyte,
// Filesize units: ISO/IEC 80000
Kibibyte,
Mebibyte,
Gibibyte,
// Duration units
Nanosecond,
Microsecond,
@ -540,6 +545,9 @@ impl Unit {
Unit::Gigabyte => "GB",
Unit::Terabyte => "TB",
Unit::Petabyte => "PB",
Unit::Kibibyte => "KiB",
Unit::Mebibyte => "MiB",
Unit::Gibibyte => "GiB",
Unit::Nanosecond => "ns",
Unit::Microsecond => "us",
Unit::Millisecond => "ms",
@ -558,13 +566,18 @@ impl Unit {
match self {
Unit::Byte => filesize(convert_number_to_u64(&size)),
Unit::Kilobyte => filesize(convert_number_to_u64(&size) * 1024),
Unit::Megabyte => filesize(convert_number_to_u64(&size) * 1024 * 1024),
Unit::Gigabyte => filesize(convert_number_to_u64(&size) * 1024 * 1024 * 1024),
Unit::Terabyte => filesize(convert_number_to_u64(&size) * 1024 * 1024 * 1024 * 1024),
Unit::Kilobyte => filesize(convert_number_to_u64(&size) * 1000),
Unit::Megabyte => filesize(convert_number_to_u64(&size) * 1000 * 1000),
Unit::Gigabyte => filesize(convert_number_to_u64(&size) * 1000 * 1000 * 1000),
Unit::Terabyte => filesize(convert_number_to_u64(&size) * 1000 * 1000 * 1000 * 1000),
Unit::Petabyte => {
filesize(convert_number_to_u64(&size) * 1024 * 1024 * 1024 * 1024 * 1024)
filesize(convert_number_to_u64(&size) * 1000 * 1000 * 1000 * 1000 * 1000)
}
Unit::Kibibyte => filesize(convert_number_to_u64(&size) * 1024),
Unit::Mebibyte => filesize(convert_number_to_u64(&size) * 1024 * 1024),
Unit::Gibibyte => filesize(convert_number_to_u64(&size) * 1024 * 1024 * 1024),
Unit::Nanosecond => duration(size.to_bigint().expect("Conversion should never fail.")),
Unit::Microsecond => {
duration(size.to_bigint().expect("Conversion should never fail.") * 1000)

View File

@ -3,7 +3,10 @@ use nu_errors::ShellError;
use std::path::{Component, Path, PathBuf};
fn is_value_tagged_dir(value: &Value) -> bool {
matches!(&value.value, UntaggedValue::Row(_) | UntaggedValue::Table(_))
matches!(
&value.value,
UntaggedValue::Row(_) | UntaggedValue::Table(_)
)
}
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]

View File

@ -759,7 +759,9 @@ fn filesize_math() {
"#
);
assert_eq!(actual.out, "1.0 MB");
assert_eq!(actual.out, "1000.0 KB");
// why 1000.0 KB instead of 1.0 MB?
// looks like `byte.get_appropriate_unit(false)` behaves this way
}
#[test]
@ -783,7 +785,7 @@ fn filesize_math3() {
"#
);
assert_eq!(actual.out, "10.2 KB");
assert_eq!(actual.out, "10.0 KB");
}
#[test]
fn filesize_math4() {
@ -794,7 +796,43 @@ fn filesize_math4() {
"#
);
assert_eq!(actual.out, "512.0 KB");
assert_eq!(actual.out, "500.0 KB");
}
#[test]
fn filesize_math5() {
let actual = nu!(
cwd: ".",
r#"
= 1001 * 1kb
"#
);
assert_eq!(actual.out, "1.0 MB");
}
#[test]
fn filesize_math6() {
let actual = nu!(
cwd: ".",
r#"
= 1001 * 1mb
"#
);
assert_eq!(actual.out, "1.0 GB");
}
#[test]
fn filesize_math7() {
let actual = nu!(
cwd: ".",
r#"
= 1001 * 1gb
"#
);
assert_eq!(actual.out, "1.0 TB");
}
#[test]