Add into duration (#4683)

* Add `into duration` command

* Avoid using unwrap()

* Use existing logic to parse duration strings
This commit is contained in:
Yutaro Ohno
2022-03-03 22:16:04 +09:00
committed by GitHub
parent 2fd42d25b1
commit 210d25f2a0
5 changed files with 328 additions and 39 deletions

View File

@ -14,7 +14,8 @@ pub use lex::{lex, Token, TokenContents};
pub use lite_parse::{lite_parse, LiteBlock};
pub use parser::{
is_math_expression_like, parse, parse_block, parse_external_call, trim_quotes, Import,
is_math_expression_like, parse, parse_block, parse_duration_bytes, parse_external_call,
trim_quotes, Import,
};
#[cfg(feature = "plugin")]

View File

@ -1881,6 +1881,22 @@ pub fn parse_duration(
) -> (Expression, Option<ParseError>) {
trace!("parsing: duration");
let bytes = working_set.get_span_contents(span);
match parse_duration_bytes(bytes, span) {
Some(expression) => (expression, None),
None => (
garbage(span),
Some(ParseError::Mismatch(
"duration".into(),
"non-duration unit".into(),
span,
)),
),
}
}
pub fn parse_duration_bytes(bytes: &[u8], span: Span) -> Option<Expression> {
fn parse_decimal_str_to_number(decimal: &str) -> Option<i64> {
let string_to_parse = format!("0.{}", decimal);
if let Ok(x) = string_to_parse.parse::<f64>() {
@ -1889,17 +1905,8 @@ pub fn parse_duration(
None
}
let bytes = working_set.get_span_contents(span);
if bytes.is_empty() || (!bytes[0].is_ascii_digit() && bytes[0] != b'-') {
return (
garbage(span),
Some(ParseError::Mismatch(
"duration".into(),
"non-duration unit".into(),
span,
)),
);
return None;
}
let token = String::from_utf8_lossy(bytes).to_string();
@ -1948,37 +1955,27 @@ pub fn parse_duration(
let lhs_span = Span::new(span.start, span.start + lhs.len());
let unit_span = Span::new(span.start + lhs.len(), span.end);
return (
Expression {
expr: Expr::ValueWithUnit(
Box::new(Expression {
expr: Expr::Int(x),
span: lhs_span,
ty: Type::Number,
custom_completion: None,
}),
Spanned {
item: unit_to_use,
span: unit_span,
},
),
span,
ty: Type::Duration,
custom_completion: None,
},
None,
);
return Some(Expression {
expr: Expr::ValueWithUnit(
Box::new(Expression {
expr: Expr::Int(x),
span: lhs_span,
ty: Type::Number,
custom_completion: None,
}),
Spanned {
item: unit_to_use,
span: unit_span,
},
),
span,
ty: Type::Duration,
custom_completion: None,
});
}
}
(
garbage(span),
Some(ParseError::Mismatch(
"duration".into(),
"non-duration unit".into(),
span,
)),
)
None
}
/// Parse a unit type, eg '10kb'