fix wrong casting with into filesize (#13110)

# Description
Fix wrong casting which is related to
https://github.com/nushell/nushell/pull/12974#discussion_r1618598336

# User-Facing Changes
AS-IS (before fixing)
```
$ "-10000PiB" | into filesize
6.2 EiB                                                         <--- Wrong casted value
$ "10000PiB" | into filesize 
-6.2 EiB                                                        <--- Wrong casted value
```

TO-BE (after fixing)
```
$ "-10000PiB" | into filesize
Error: nu:🐚:cant_convert

  × Can't convert to filesize.
   ╭─[entry #6:1:1]
 1 │ "-10000PiB" | into filesize
   · ─────┬─────
   ·      ╰── can't convert string to filesize
   ╰────

$ "10000PiB" | into filesize
Error: nu:🐚:cant_convert

  × Can't convert to filesize.
   ╭─[entry #7:1:1]
 1 │ "10000PiB" | into filesize
   · ─────┬────
   ·      ╰── can't convert string to filesize
   ╰────
```
This commit is contained in:
Sang-Heon Jeon 2024-06-10 11:43:17 +09:00 committed by GitHub
parent 5ac3ad61c4
commit dc76183cd5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 30 additions and 5 deletions

View File

@ -122,7 +122,7 @@ pub fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
Value::Filesize { .. } => input.clone(), Value::Filesize { .. } => input.clone(),
Value::Int { val, .. } => Value::filesize(*val, value_span), Value::Int { val, .. } => Value::filesize(*val, value_span),
Value::Float { val, .. } => Value::filesize(*val as i64, value_span), Value::Float { val, .. } => Value::filesize(*val as i64, value_span),
Value::String { val, .. } => match int_from_string(val, value_span) { Value::String { val, .. } => match i64_from_string(val, value_span) {
Ok(val) => Value::filesize(val, value_span), Ok(val) => Value::filesize(val, value_span),
Err(error) => Value::error(error, value_span), Err(error) => Value::error(error, value_span),
}, },
@ -139,7 +139,7 @@ pub fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
} }
} }
fn int_from_string(a_string: &str, span: Span) -> Result<i64, ShellError> { fn i64_from_string(a_string: &str, span: Span) -> Result<i64, ShellError> {
// Get the Locale so we know what the thousands separator is // Get the Locale so we know what the thousands separator is
let locale = get_system_locale(); let locale = get_system_locale();
@ -151,24 +151,35 @@ fn int_from_string(a_string: &str, span: Span) -> Result<i64, ShellError> {
// Hadle negative file size // Hadle negative file size
if let Some(stripped_negative_string) = clean_string.strip_prefix('-') { if let Some(stripped_negative_string) = clean_string.strip_prefix('-') {
match stripped_negative_string.parse::<bytesize::ByteSize>() { match stripped_negative_string.parse::<bytesize::ByteSize>() {
Ok(n) => Ok(-(n.as_u64() as i64)), Ok(n) => i64_from_byte_size(n, true, span),
Err(_) => Err(string_convert_error(span)), Err(_) => Err(string_convert_error(span)),
} }
} else if let Some(stripped_positive_string) = clean_string.strip_prefix('+') { } else if let Some(stripped_positive_string) = clean_string.strip_prefix('+') {
match stripped_positive_string.parse::<bytesize::ByteSize>() { match stripped_positive_string.parse::<bytesize::ByteSize>() {
Ok(n) if stripped_positive_string.starts_with(|c: char| c.is_ascii_digit()) => { Ok(n) if stripped_positive_string.starts_with(|c: char| c.is_ascii_digit()) => {
Ok(n.as_u64() as i64) i64_from_byte_size(n, false, span)
} }
_ => Err(string_convert_error(span)), _ => Err(string_convert_error(span)),
} }
} else { } else {
match clean_string.parse::<bytesize::ByteSize>() { match clean_string.parse::<bytesize::ByteSize>() {
Ok(n) => Ok(n.as_u64() as i64), Ok(n) => i64_from_byte_size(n, false, span),
Err(_) => Err(string_convert_error(span)), Err(_) => Err(string_convert_error(span)),
} }
} }
} }
fn i64_from_byte_size(
byte_size: bytesize::ByteSize,
is_negative: bool,
span: Span,
) -> Result<i64, ShellError> {
match i64::try_from(byte_size.as_u64()) {
Ok(n) => Ok(if is_negative { -n } else { n }),
Err(_) => Err(string_convert_error(span)),
}
}
fn string_convert_error(span: Span) -> ShellError { fn string_convert_error(span: Span) -> ShellError {
ShellError::CantConvert { ShellError::CantConvert {
to_type: "filesize".into(), to_type: "filesize".into(),

View File

@ -76,6 +76,13 @@ fn into_filesize_wrong_negative_str_filesize() {
assert!(actual.err.contains("can't convert string to filesize")); assert!(actual.err.contains("can't convert string to filesize"));
} }
#[test]
fn into_filesize_large_negative_str_filesize() {
let actual = nu!("'-10000PiB' | into filesize");
assert!(actual.err.contains("can't convert string to filesize"));
}
#[test] #[test]
fn into_filesize_negative_str() { fn into_filesize_negative_str() {
let actual = nu!("'-1' | into filesize"); let actual = nu!("'-1' | into filesize");
@ -104,6 +111,13 @@ fn into_filesize_wrong_positive_str_filesize() {
assert!(actual.err.contains("can't convert string to filesize")); assert!(actual.err.contains("can't convert string to filesize"));
} }
#[test]
fn into_filesize_large_positive_str_filesize() {
let actual = nu!("'+10000PiB' | into filesize");
assert!(actual.err.contains("can't convert string to filesize"));
}
#[test] #[test]
fn into_filesize_positive_str() { fn into_filesize_positive_str() {
let actual = nu!("'+1' | into filesize"); let actual = nu!("'+1' | into filesize");