forked from extern/nushell
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
@ -1231,128 +1231,7 @@ pub fn eval_variable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn compute(size: i64, unit: Unit, span: Span) -> Value {
|
fn compute(size: i64, unit: Unit, span: Span) -> Value {
|
||||||
match unit {
|
unit.to_value(size, span)
|
||||||
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(),
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::{Expr, MatchPattern, Pattern, RangeInclusion},
|
ast::{Expr, MatchPattern, Pattern, RangeInclusion},
|
||||||
Span, Unit, Value, VarId,
|
Span, Value, VarId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait Matcher {
|
pub trait Matcher {
|
||||||
@ -145,55 +145,10 @@ impl Matcher for Pattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::ValueWithUnit(amount, unit) => {
|
Expr::ValueWithUnit(amount, unit) => {
|
||||||
if let Value::Filesize { val, .. } = &value {
|
let span = unit.span;
|
||||||
// FIXME: we probably want this math in one place that both the
|
|
||||||
// pattern matcher and the eval engine can get to it
|
if let Expr::Int(size) = amount.expr {
|
||||||
match &amount.expr {
|
&unit.item.to_value(size, span) == value
|
||||||
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,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::{ShellError, Span, Value};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
@ -31,3 +32,130 @@ pub enum Unit {
|
|||||||
Day,
|
Day,
|
||||||
Week,
|
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 New Issue
Block a user