diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index f809092b9..f48791d1f 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1231,128 +1231,7 @@ pub fn eval_variable( } fn compute(size: i64, unit: Unit, span: Span) -> Value { - match unit { - Unit::Byte => Value::Filesize { val: size, span }, - Unit::Kilobyte => Value::Filesize { - val: size * 1000, - span, - }, - Unit::Megabyte => Value::Filesize { - val: size * 1000 * 1000, - span, - }, - Unit::Gigabyte => Value::Filesize { - val: size * 1000 * 1000 * 1000, - span, - }, - Unit::Terabyte => Value::Filesize { - val: size * 1000 * 1000 * 1000 * 1000, - span, - }, - Unit::Petabyte => Value::Filesize { - val: size * 1000 * 1000 * 1000 * 1000 * 1000, - span, - }, - Unit::Exabyte => Value::Filesize { - val: size * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, - span, - }, - Unit::Zettabyte => Value::Filesize { - val: size * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, - span, - }, - - Unit::Kibibyte => Value::Filesize { - val: size * 1024, - span, - }, - Unit::Mebibyte => Value::Filesize { - val: size * 1024 * 1024, - span, - }, - Unit::Gibibyte => Value::Filesize { - val: size * 1024 * 1024 * 1024, - span, - }, - Unit::Tebibyte => Value::Filesize { - val: size * 1024 * 1024 * 1024 * 1024, - span, - }, - Unit::Pebibyte => Value::Filesize { - val: size * 1024 * 1024 * 1024 * 1024 * 1024, - span, - }, - Unit::Exbibyte => Value::Filesize { - val: size * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, - span, - }, - Unit::Zebibyte => Value::Filesize { - val: size * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, - span, - }, - - Unit::Nanosecond => Value::Duration { val: size, span }, - Unit::Microsecond => Value::Duration { - val: size * 1000, - span, - }, - Unit::Millisecond => Value::Duration { - val: size * 1000 * 1000, - span, - }, - Unit::Second => Value::Duration { - val: size * 1000 * 1000 * 1000, - span, - }, - Unit::Minute => match size.checked_mul(1000 * 1000 * 1000 * 60) { - Some(val) => Value::Duration { val, span }, - None => Value::Error { - error: Box::new(ShellError::GenericError( - "duration too large".into(), - "duration too large".into(), - Some(span), - None, - Vec::new(), - )), - }, - }, - Unit::Hour => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60) { - Some(val) => Value::Duration { val, span }, - None => Value::Error { - error: Box::new(ShellError::GenericError( - "duration too large".into(), - "duration too large".into(), - Some(span), - None, - Vec::new(), - )), - }, - }, - Unit::Day => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24) { - Some(val) => Value::Duration { val, span }, - None => Value::Error { - error: Box::new(ShellError::GenericError( - "duration too large".into(), - "duration too large".into(), - Some(span), - None, - Vec::new(), - )), - }, - }, - Unit::Week => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24 * 7) { - Some(val) => Value::Duration { val, span }, - None => Value::Error { - error: Box::new(ShellError::GenericError( - "duration too large".into(), - "duration too large".into(), - Some(span), - None, - Vec::new(), - )), - }, - }, - } + unit.to_value(size, span) } #[allow(clippy::too_many_arguments)] diff --git a/crates/nu-protocol/src/engine/pattern_match.rs b/crates/nu-protocol/src/engine/pattern_match.rs index 68e59dc2b..d302e3bff 100644 --- a/crates/nu-protocol/src/engine/pattern_match.rs +++ b/crates/nu-protocol/src/engine/pattern_match.rs @@ -1,6 +1,6 @@ use crate::{ ast::{Expr, MatchPattern, Pattern, RangeInclusion}, - Span, Unit, Value, VarId, + Span, Value, VarId, }; pub trait Matcher { @@ -145,55 +145,10 @@ impl Matcher for Pattern { } } Expr::ValueWithUnit(amount, unit) => { - if let Value::Filesize { val, .. } = &value { - // FIXME: we probably want this math in one place that both the - // pattern matcher and the eval engine can get to it - match &amount.expr { - Expr::Int(amount) => match &unit.item { - Unit::Byte => amount == val, - Unit::Kilobyte => *val == amount * 1000, - Unit::Megabyte => *val == amount * 1000 * 1000, - Unit::Gigabyte => *val == amount * 1000 * 1000 * 1000, - Unit::Petabyte => *val == amount * 1000 * 1000 * 1000 * 1000, - Unit::Exabyte => { - *val == amount * 1000 * 1000 * 1000 * 1000 * 1000 - } - Unit::Zettabyte => { - *val == amount * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 - } - Unit::Kibibyte => *val == amount * 1024, - Unit::Mebibyte => *val == amount * 1024 * 1024, - Unit::Gibibyte => *val == amount * 1024 * 1024 * 1024, - Unit::Pebibyte => *val == amount * 1024 * 1024 * 1024 * 1024, - Unit::Exbibyte => { - *val == amount * 1024 * 1024 * 1024 * 1024 * 1024 - } - Unit::Zebibyte => { - *val == amount * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 - } - _ => false, - }, - _ => false, - } - } else if let Value::Duration { val, .. } = &value { - // FIXME: we probably want this math in one place that both the - // pattern matcher and the eval engine can get to it - match &amount.expr { - Expr::Int(amount) => match &unit.item { - Unit::Nanosecond => val == amount, - Unit::Microsecond => *val == amount * 1000, - Unit::Millisecond => *val == amount * 1000 * 1000, - Unit::Second => *val == amount * 1000 * 1000 * 1000, - Unit::Minute => *val == amount * 1000 * 1000 * 1000 * 60, - Unit::Hour => *val == amount * 1000 * 1000 * 1000 * 60 * 60, - Unit::Day => *val == amount * 1000 * 1000 * 1000 * 60 * 60 * 24, - Unit::Week => { - *val == amount * 1000 * 1000 * 1000 * 60 * 60 * 24 * 7 - } - _ => false, - }, - _ => false, - } + let span = unit.span; + + if let Expr::Int(size) = amount.expr { + &unit.item.to_value(size, span) == value } else { false } diff --git a/crates/nu-protocol/src/value/unit.rs b/crates/nu-protocol/src/value/unit.rs index 21f7348cb..192d9cba2 100644 --- a/crates/nu-protocol/src/value/unit.rs +++ b/crates/nu-protocol/src/value/unit.rs @@ -1,3 +1,4 @@ +use crate::{ShellError, Span, Value}; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] @@ -31,3 +32,130 @@ pub enum Unit { Day, Week, } + +impl Unit { + pub fn to_value(&self, size: i64, span: Span) -> Value { + match self { + Unit::Byte => Value::Filesize { val: size, span }, + Unit::Kilobyte => Value::Filesize { + val: size * 1000, + span, + }, + Unit::Megabyte => Value::Filesize { + val: size * 1000 * 1000, + span, + }, + Unit::Gigabyte => Value::Filesize { + val: size * 1000 * 1000 * 1000, + span, + }, + Unit::Terabyte => Value::Filesize { + val: size * 1000 * 1000 * 1000 * 1000, + span, + }, + Unit::Petabyte => Value::Filesize { + val: size * 1000 * 1000 * 1000 * 1000 * 1000, + span, + }, + Unit::Exabyte => Value::Filesize { + val: size * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, + span, + }, + Unit::Zettabyte => Value::Filesize { + val: size * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, + span, + }, + + Unit::Kibibyte => Value::Filesize { + val: size * 1024, + span, + }, + Unit::Mebibyte => Value::Filesize { + val: size * 1024 * 1024, + span, + }, + Unit::Gibibyte => Value::Filesize { + val: size * 1024 * 1024 * 1024, + span, + }, + Unit::Tebibyte => Value::Filesize { + val: size * 1024 * 1024 * 1024 * 1024, + span, + }, + Unit::Pebibyte => Value::Filesize { + val: size * 1024 * 1024 * 1024 * 1024 * 1024, + span, + }, + Unit::Exbibyte => Value::Filesize { + val: size * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, + span, + }, + Unit::Zebibyte => Value::Filesize { + val: size * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, + span, + }, + + Unit::Nanosecond => Value::Duration { val: size, span }, + Unit::Microsecond => Value::Duration { + val: size * 1000, + span, + }, + Unit::Millisecond => Value::Duration { + val: size * 1000 * 1000, + span, + }, + Unit::Second => Value::Duration { + val: size * 1000 * 1000 * 1000, + span, + }, + Unit::Minute => match size.checked_mul(1000 * 1000 * 1000 * 60) { + Some(val) => Value::Duration { val, span }, + None => Value::Error { + error: Box::new(ShellError::GenericError( + "duration too large".into(), + "duration too large".into(), + Some(span), + None, + Vec::new(), + )), + }, + }, + Unit::Hour => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60) { + Some(val) => Value::Duration { val, span }, + None => Value::Error { + error: Box::new(ShellError::GenericError( + "duration too large".into(), + "duration too large".into(), + Some(span), + None, + Vec::new(), + )), + }, + }, + Unit::Day => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24) { + Some(val) => Value::Duration { val, span }, + None => Value::Error { + error: Box::new(ShellError::GenericError( + "duration too large".into(), + "duration too large".into(), + Some(span), + None, + Vec::new(), + )), + }, + }, + Unit::Week => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24 * 7) { + Some(val) => Value::Duration { val, span }, + None => Value::Error { + error: Box::new(ShellError::GenericError( + "duration too large".into(), + "duration too large".into(), + Some(span), + None, + Vec::new(), + )), + }, + }, + } + } +}