mirror of
https://github.com/nushell/nushell
synced 2024-11-10 07:04:13 +00:00
make the pattern-matcher and eval engine use the same unit computation (#8973)
# Description
this pr adresses
[this](7413ef2824/crates/nu-protocol/src/engine/pattern_match.rs (L149)
)
'fix me'
This commit is contained in:
parent
6cbd42974b
commit
2254805a6d
3 changed files with 134 additions and 172 deletions
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
)),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue