mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-10 14:24:40 +03:00
Change StringNumber to BigInteger
This commit is contained in:
parent
1c24185aeb
commit
112d0e9457
@ -68,7 +68,7 @@ impl Number {
|
||||
Number::Float(f) => {
|
||||
serde_json::Value::Number(serde_json::Number::from_f64(*f).unwrap())
|
||||
}
|
||||
Number::String(s) => {
|
||||
Number::BigInteger(s) => {
|
||||
let number = serde_json::Number::from_str(s).unwrap();
|
||||
serde_json::Value::Number(number)
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use std::fmt;
|
||||
pub enum Number {
|
||||
Float(f64),
|
||||
Integer(i64),
|
||||
String(String),
|
||||
BigInteger(String),
|
||||
}
|
||||
|
||||
// You must implement it yourself because of the Float
|
||||
@ -34,7 +34,7 @@ impl PartialEq for Number {
|
||||
match (self, other) {
|
||||
(Number::Float(v1), Number::Float(v2)) => (v1 - v2).abs() < f64::EPSILON,
|
||||
(Number::Integer(v1), Number::Integer(v2)) => v1 == v2,
|
||||
(Number::String(v1), Number::String(v2)) => v1 == v2,
|
||||
(Number::BigInteger(v1), Number::BigInteger(v2)) => v1 == v2,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -47,7 +47,7 @@ impl fmt::Display for Number {
|
||||
let value = match self {
|
||||
Number::Float(f) => format_float(*f),
|
||||
Number::Integer(x) => x.to_string(),
|
||||
Number::String(s) => s.to_string(),
|
||||
Number::BigInteger(s) => s.to_string(),
|
||||
};
|
||||
write!(f, "{value}")
|
||||
}
|
||||
@ -66,7 +66,7 @@ impl Number {
|
||||
match self {
|
||||
Number::Float(_) => "float".to_string(),
|
||||
Number::Integer(_) => "integer".to_string(),
|
||||
Number::String(_) => "string".to_string(),
|
||||
Number::BigInteger(_) => "string".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -150,10 +150,13 @@ mod tests {
|
||||
assert_eq!(Number::from(1.0).to_string(), "1.0".to_string());
|
||||
assert_eq!(Number::from(1.1).to_string(), "1.1".to_string());
|
||||
assert_eq!(
|
||||
Number::String("1.1".to_string()).to_string(),
|
||||
Number::BigInteger("1.1".to_string()).to_string(),
|
||||
"1.1".to_string()
|
||||
);
|
||||
assert_eq!(Number::String("1".to_string()).to_string(), "1".to_string());
|
||||
assert_eq!(
|
||||
Number::BigInteger("1".to_string()).to_string(),
|
||||
"1".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -173,9 +176,9 @@ mod tests {
|
||||
let float_min = Number::from(f64::MIN);
|
||||
let float_max = Number::from(f64::MAX);
|
||||
|
||||
let number_one = Number::String("1".to_string());
|
||||
let number_two = Number::String("2".to_string());
|
||||
let number_two_with_decimal = Number::String("2.0".to_string());
|
||||
let number_one = Number::BigInteger("1".to_string());
|
||||
let number_two = Number::BigInteger("2".to_string());
|
||||
let number_two_with_decimal = Number::BigInteger("2.0".to_string());
|
||||
|
||||
assert_eq!(integer_minus_one.cmp_value(&integer_zero), Ordering::Less);
|
||||
|
||||
|
@ -19,8 +19,8 @@ use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use hurl_core::ast::{
|
||||
BooleanOption, Entry, EntryOption, Float, NaturalOption, OptionKind, Retry, RetryOption,
|
||||
SectionValue, VariableDefinition, VariableValue,
|
||||
BooleanOption, Entry, EntryOption, Float, NaturalOption, Number as AstNumber, OptionKind,
|
||||
Retry, RetryOption, SectionValue, VariableDefinition, VariableValue,
|
||||
};
|
||||
|
||||
use crate::http::{IpResolve, RequestedHttpVersion};
|
||||
@ -344,8 +344,7 @@ fn eval_variable_value(
|
||||
match variable_value {
|
||||
VariableValue::Null => Ok(Value::Null),
|
||||
VariableValue::Bool(v) => Ok(Value::Bool(*v)),
|
||||
VariableValue::Integer(v) => Ok(Value::Number(Number::Integer(*v))),
|
||||
VariableValue::Float(Float { value, .. }) => Ok(Value::Number(Number::Float(*value))),
|
||||
VariableValue::Number(v) => Ok(eval_number(v)),
|
||||
VariableValue::String(template) => {
|
||||
let s = template::eval_template(template, variables)?;
|
||||
Ok(Value::String(s))
|
||||
@ -353,6 +352,14 @@ fn eval_variable_value(
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_number(number: &AstNumber) -> Value {
|
||||
match number {
|
||||
AstNumber::Float(Float { value, .. }) => Value::Number(Number::Float(*value)),
|
||||
AstNumber::Integer(value) => Value::Number(Number::Integer(*value)),
|
||||
AstNumber::BigInteger(value) => Value::Number(Number::BigInteger(value.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hurl_core::ast::{Expr, Pos, SourceInfo, Variable, Whitespace};
|
||||
|
@ -132,7 +132,7 @@ impl Number {
|
||||
match self {
|
||||
Number::Float(f) => format!("float <{}>", format_float(*f)),
|
||||
Number::Integer(v) => format!("int <{v}>"),
|
||||
Number::String(s) => format!("number <{s}>"),
|
||||
Number::BigInteger(s) => format!("number <{s}>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,7 +160,7 @@ impl Number {
|
||||
match self {
|
||||
Number::Float(f) => format!("float <{}>", format_float(*f)),
|
||||
Number::Integer(value) => format!("integer <{value}>"),
|
||||
Number::String(s) => format!("number <{s}>"),
|
||||
Number::BigInteger(s) => format!("number <{s}>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -523,7 +523,8 @@ fn eval_match(
|
||||
/// Evaluates if an `actual` value is an integer.
|
||||
fn eval_is_integer(actual: &Value) -> Result<AssertResult, Error> {
|
||||
Ok(AssertResult {
|
||||
success: matches!(actual, Value::Number(Number::Integer(_))),
|
||||
success: matches!(actual, Value::Number(Number::Integer(_)))
|
||||
|| matches!(actual, Value::Number(Number::BigInteger(_))),
|
||||
actual: actual.display(),
|
||||
expected: "integer".to_string(),
|
||||
type_mismatch: false,
|
||||
|
@ -74,6 +74,6 @@ fn eval_number(number: &Number) -> ValueNumber {
|
||||
match number {
|
||||
Number::Float(value) => ValueNumber::Float(value.value),
|
||||
Number::Integer(value) => ValueNumber::Integer(*value),
|
||||
Number::String(value) => ValueNumber::String(value.clone()),
|
||||
Number::BigInteger(value) => ValueNumber::BigInteger(value.clone()),
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ impl Value {
|
||||
} else if n.is_i64() {
|
||||
Value::Number(Number::from(n.as_i64().unwrap()))
|
||||
} else {
|
||||
Value::Number(Number::String(n.to_string()))
|
||||
Value::Number(Number::BigInteger(n.to_string()))
|
||||
}
|
||||
}
|
||||
serde_json::Value::String(s) => Value::String(s.to_string()),
|
||||
@ -505,7 +505,14 @@ pub mod tests {
|
||||
serde_json::from_str("1000000000000000000000").unwrap();
|
||||
assert_eq!(
|
||||
Value::from_json(&json_number),
|
||||
Value::Number(Number::String("1000000000000000000000".to_string()))
|
||||
Value::Number(Number::BigInteger("1000000000000000000000".to_string()))
|
||||
);
|
||||
|
||||
let json_number: serde_json::Value =
|
||||
serde_json::from_str("1000000000000000000000.5").unwrap();
|
||||
assert_eq!(
|
||||
Value::from_json(&json_number),
|
||||
Value::Number(Number::Float(1000000000000000000000.5f64))
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -602,7 +602,7 @@ pub struct Filename {
|
||||
pub enum Number {
|
||||
Float(Float),
|
||||
Integer(i64),
|
||||
String(String),
|
||||
BigInteger(String),
|
||||
}
|
||||
|
||||
// keep Number terminology for both Integer and Decimal Numbers
|
||||
@ -834,8 +834,7 @@ pub struct VariableDefinition {
|
||||
pub enum VariableValue {
|
||||
Null,
|
||||
Bool(bool),
|
||||
Integer(i64),
|
||||
Float(Float),
|
||||
Number(Number),
|
||||
String(Template),
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ impl fmt::Display for Number {
|
||||
match self {
|
||||
Number::Float(value) => write!(f, "{}", value),
|
||||
Number::Integer(value) => write!(f, "{}", value),
|
||||
Number::String(value) => write!(f, "{}", value),
|
||||
Number::BigInteger(value) => write!(f, "{}", value),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -207,8 +207,7 @@ impl fmt::Display for VariableValue {
|
||||
let s = match self {
|
||||
VariableValue::Null => "null".to_string(),
|
||||
VariableValue::Bool(value) => value.to_string(),
|
||||
VariableValue::Integer(n) => n.to_string(),
|
||||
VariableValue::Float(x) => x.to_string(),
|
||||
VariableValue::Number(n) => n.to_string(),
|
||||
VariableValue::String(s) => s.to_string(),
|
||||
};
|
||||
write!(f, "{}", s)
|
||||
|
@ -271,8 +271,7 @@ impl HtmlFormatter {
|
||||
match option {
|
||||
VariableValue::Null => self.fmt_span("null", "null"),
|
||||
VariableValue::Bool(v) => self.fmt_bool(*v),
|
||||
VariableValue::Integer(v) => self.fmt_number(v),
|
||||
VariableValue::Float(v) => self.fmt_number(&v.encoded),
|
||||
VariableValue::Number(v) => self.fmt_number(v),
|
||||
VariableValue::String(t) => self.fmt_template(t),
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
*
|
||||
*/
|
||||
use crate::ast::*;
|
||||
use crate::parser::combinators::*;
|
||||
use crate::parser::error::*;
|
||||
use crate::parser::primitives::try_literal;
|
||||
use crate::parser::reader::Reader;
|
||||
@ -61,36 +60,6 @@ pub fn natural(reader: &mut Reader) -> ParseResult<u64> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn number(reader: &mut Reader) -> ParseResult<Number> {
|
||||
choice(
|
||||
&[
|
||||
|p1| match float(p1) {
|
||||
Ok(value) => Ok(Number::Float(value)),
|
||||
Err(e) => Err(e.recoverable()),
|
||||
},
|
||||
|p1| match integer(p1) {
|
||||
Ok(value) => Ok(Number::Integer(value)),
|
||||
Err(e) => Err(e.recoverable()),
|
||||
},
|
||||
|p1| match string_number(p1) {
|
||||
Ok(value) => Ok(Number::String(value)),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
],
|
||||
reader,
|
||||
)
|
||||
.map_err(|e| {
|
||||
let inner = if e.recoverable {
|
||||
ParseError::Expecting {
|
||||
value: "number".to_string(),
|
||||
}
|
||||
} else {
|
||||
e.inner
|
||||
};
|
||||
Error::new(e.pos, true, inner)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn integer(reader: &mut Reader) -> ParseResult<i64> {
|
||||
let sign = match try_literal("-", reader) {
|
||||
Err(_) => 1,
|
||||
@ -100,70 +69,58 @@ pub fn integer(reader: &mut Reader) -> ParseResult<i64> {
|
||||
Ok(sign * (nat as i64))
|
||||
}
|
||||
|
||||
pub fn float(reader: &mut Reader) -> ParseResult<Float> {
|
||||
// non recoverable after the dot
|
||||
// an integer is parsed ok as float => no like a computer language
|
||||
pub fn number(reader: &mut Reader) -> ParseResult<Number> {
|
||||
let start = reader.state;
|
||||
let sign = match try_literal("-", reader) {
|
||||
Err(_) => "",
|
||||
Ok(_) => "-",
|
||||
};
|
||||
let nat = natural(reader)?;
|
||||
try_literal(".", reader)?;
|
||||
|
||||
if reader.is_eof() {
|
||||
let inner = ParseError::Expecting {
|
||||
value: String::from("natural"),
|
||||
};
|
||||
return Err(Error::new(reader.state.pos, false, inner));
|
||||
}
|
||||
|
||||
let s = reader.read_while(|c| c.is_ascii_digit());
|
||||
if s.is_empty() {
|
||||
let inner = ParseError::Expecting {
|
||||
value: String::from("natural"),
|
||||
};
|
||||
return Err(Error::new(reader.state.pos, false, inner));
|
||||
}
|
||||
match format!("{sign}{nat}.{s}").parse() {
|
||||
Ok(value) => {
|
||||
let encoded = reader.peek_back(start.cursor);
|
||||
Ok(Float { value, encoded })
|
||||
}
|
||||
Err(_) => {
|
||||
let inner = ParseError::Expecting {
|
||||
value: String::from("float"),
|
||||
};
|
||||
Err(Error::new(start.pos, false, inner))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn string_number(reader: &mut Reader) -> ParseResult<String> {
|
||||
let sign = match try_literal("-", reader) {
|
||||
Err(_) => "",
|
||||
Ok(_) => "-",
|
||||
};
|
||||
let integer = reader.read_while(|c| c.is_ascii_digit());
|
||||
if integer.is_empty() {
|
||||
let integer_digits = reader.read_while(|c| c.is_ascii_digit());
|
||||
if integer_digits.is_empty() {
|
||||
let inner = ParseError::Expecting {
|
||||
value: "number".to_string(),
|
||||
};
|
||||
return Err(Error::new(reader.state.pos, true, inner));
|
||||
|
||||
// if the first digit is zero, you should not have any more digits
|
||||
} else if integer_digits.len() > 1 && integer_digits.starts_with('0') {
|
||||
let save = reader.state;
|
||||
let inner = ParseError::Expecting {
|
||||
value: String::from("natural"),
|
||||
};
|
||||
return Err(Error::new(save.pos, false, inner));
|
||||
}
|
||||
let decimal = if try_literal(".", reader).is_ok() {
|
||||
let s = reader.read_while(|c| c.is_ascii_digit());
|
||||
if s.is_empty() {
|
||||
|
||||
// Float
|
||||
if try_literal(".", reader).is_ok() {
|
||||
let save = reader.state;
|
||||
let decimal_digits = reader.read_while(|c| c.is_ascii_digit());
|
||||
if decimal_digits.is_empty() {
|
||||
let inner = ParseError::Expecting {
|
||||
value: "decimals".to_string(),
|
||||
value: String::from("decimal digits"),
|
||||
};
|
||||
return Err(Error::new(reader.state.pos, false, inner));
|
||||
return Err(Error::new(save.pos, false, inner));
|
||||
}
|
||||
format!(".{s}")
|
||||
match format!("{sign}{integer_digits}.{decimal_digits}").parse() {
|
||||
Ok(value) => {
|
||||
let encoded = reader.peek_back(start.cursor);
|
||||
Ok(Number::Float(Float { value, encoded }))
|
||||
}
|
||||
Err(_) => {
|
||||
let inner = ParseError::Expecting {
|
||||
value: String::from("float"),
|
||||
};
|
||||
Err(Error::new(start.pos, false, inner))
|
||||
}
|
||||
}
|
||||
|
||||
// Integer or BigInteger
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
Ok(format!("{sign}{integer}{decimal}"))
|
||||
match format!("{sign}{integer_digits}").parse() {
|
||||
Ok(value) => Ok(Number::Integer(value)),
|
||||
Err(_) => Ok(Number::BigInteger(integer_digits)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -177,10 +134,6 @@ mod tests {
|
||||
assert_eq!(natural(&mut reader).unwrap(), 0);
|
||||
assert_eq!(reader.state.cursor, 1);
|
||||
|
||||
let mut reader = Reader::new("0.");
|
||||
assert_eq!(natural(&mut reader).unwrap(), 0);
|
||||
assert_eq!(reader.state.cursor, 1);
|
||||
|
||||
let mut reader = Reader::new("10x");
|
||||
assert_eq!(natural(&mut reader).unwrap(), 10);
|
||||
assert_eq!(reader.state.cursor, 2);
|
||||
@ -223,9 +176,49 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_number() {
|
||||
let mut reader = Reader::new("1");
|
||||
assert_eq!(number(&mut reader).unwrap(), Number::Integer(1));
|
||||
fn test_integer() {
|
||||
let mut reader = Reader::new("0");
|
||||
assert_eq!(integer(&mut reader).unwrap(), 0);
|
||||
assert_eq!(reader.state.cursor, 1);
|
||||
|
||||
let mut reader = Reader::new("-1");
|
||||
assert_eq!(integer(&mut reader).unwrap(), -1);
|
||||
assert_eq!(reader.state.cursor, 2);
|
||||
|
||||
let mut reader = Reader::new("0");
|
||||
assert_eq!(number(&mut reader).unwrap(), Number::Integer(0));
|
||||
assert_eq!(reader.state.cursor, 1);
|
||||
|
||||
let mut reader = Reader::new("10x");
|
||||
assert_eq!(number(&mut reader).unwrap(), Number::Integer(10));
|
||||
assert_eq!(reader.state.cursor, 2);
|
||||
|
||||
let mut reader = Reader::new("-10x");
|
||||
assert_eq!(number(&mut reader).unwrap(), Number::Integer(-10));
|
||||
assert_eq!(reader.state.cursor, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float() {
|
||||
let mut reader = Reader::new("1.0");
|
||||
assert_eq!(
|
||||
number(&mut reader).unwrap(),
|
||||
Number::Float(Float {
|
||||
value: 1.0,
|
||||
encoded: "1.0".to_string()
|
||||
})
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 3);
|
||||
|
||||
let mut reader = Reader::new("-1.0");
|
||||
assert_eq!(
|
||||
number(&mut reader).unwrap(),
|
||||
Number::Float(Float {
|
||||
value: -1.0,
|
||||
encoded: "-1.0".to_string()
|
||||
})
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 4);
|
||||
|
||||
let mut reader = Reader::new("1.1");
|
||||
assert_eq!(
|
||||
@ -235,16 +228,84 @@ mod tests {
|
||||
encoded: "1.1".to_string()
|
||||
})
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 3);
|
||||
|
||||
let mut reader = Reader::new("1000000000000000000000");
|
||||
let mut reader = Reader::new("1.100");
|
||||
assert_eq!(
|
||||
number(&mut reader).unwrap(),
|
||||
Number::String("1000000000000000000000".to_string())
|
||||
Number::Float(Float {
|
||||
value: 1.1,
|
||||
encoded: "1.100".to_string()
|
||||
})
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 5);
|
||||
|
||||
let mut reader = Reader::new("1.01");
|
||||
assert_eq!(
|
||||
number(&mut reader).unwrap(),
|
||||
Number::Float(Float {
|
||||
value: 1.01,
|
||||
encoded: "1.01".to_string()
|
||||
})
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 4);
|
||||
|
||||
let mut reader = Reader::new("1.010");
|
||||
assert_eq!(
|
||||
number(&mut reader).unwrap(),
|
||||
Number::Float(Float {
|
||||
value: 1.01,
|
||||
encoded: "1.010".to_string()
|
||||
})
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 5);
|
||||
|
||||
// provide more digits than necessary
|
||||
let mut reader = Reader::new("-0.3333333333333333333");
|
||||
assert_eq!(
|
||||
number(&mut reader).unwrap(),
|
||||
Number::Float(Float {
|
||||
value: -0.3333333333333333,
|
||||
encoded: "-0.3333333333333333333".to_string()
|
||||
})
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 22);
|
||||
|
||||
let mut reader = Reader::new("1000000000000000000000.5");
|
||||
assert_eq!(
|
||||
number(&mut reader).unwrap(),
|
||||
Number::Float(Float {
|
||||
value: 1000000000000000000000.0,
|
||||
encoded: "1000000000000000000000.5".to_string()
|
||||
})
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 24);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_number_error() {
|
||||
let mut reader = Reader::new("");
|
||||
let error = number(&mut reader).err().unwrap();
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("number")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 1 });
|
||||
assert!(error.recoverable);
|
||||
|
||||
let mut reader = Reader::new("-");
|
||||
let error = number(&mut reader).err().unwrap();
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("number")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 2 });
|
||||
assert!(error.recoverable);
|
||||
|
||||
let mut reader = Reader::new("x");
|
||||
let error = number(&mut reader).err().unwrap();
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 1 });
|
||||
@ -255,208 +316,16 @@ mod tests {
|
||||
}
|
||||
);
|
||||
assert!(error.recoverable);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_integer() {
|
||||
let mut reader = Reader::new("1");
|
||||
assert_eq!(integer(&mut reader).unwrap(), 1);
|
||||
|
||||
let mut reader = Reader::new("1.1");
|
||||
assert_eq!(integer(&mut reader).unwrap(), 1);
|
||||
|
||||
let mut reader = Reader::new("-1.1");
|
||||
assert_eq!(integer(&mut reader).unwrap(), -1);
|
||||
|
||||
let mut reader = Reader::new("x");
|
||||
let error = integer(&mut reader).err().unwrap();
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 1 });
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("natural")
|
||||
}
|
||||
);
|
||||
assert!(error.recoverable);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float() {
|
||||
let mut reader = Reader::new("1.0");
|
||||
assert_eq!(
|
||||
float(&mut reader).unwrap(),
|
||||
Float {
|
||||
value: 1.0,
|
||||
encoded: "1.0".to_string()
|
||||
}
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 3);
|
||||
|
||||
let mut reader = Reader::new("-1.0");
|
||||
assert_eq!(
|
||||
float(&mut reader).unwrap(),
|
||||
Float {
|
||||
value: -1.0,
|
||||
encoded: "-1.0".to_string()
|
||||
}
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 4);
|
||||
|
||||
let mut reader = Reader::new("1.1");
|
||||
assert_eq!(
|
||||
float(&mut reader).unwrap(),
|
||||
Float {
|
||||
value: 1.1,
|
||||
encoded: "1.1".to_string()
|
||||
}
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 3);
|
||||
|
||||
let mut reader = Reader::new("1.100");
|
||||
assert_eq!(
|
||||
float(&mut reader).unwrap(),
|
||||
Float {
|
||||
value: 1.1,
|
||||
encoded: "1.100".to_string()
|
||||
}
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 5);
|
||||
|
||||
let mut reader = Reader::new("1.01");
|
||||
assert_eq!(
|
||||
float(&mut reader).unwrap(),
|
||||
Float {
|
||||
value: 1.01,
|
||||
encoded: "1.01".to_string()
|
||||
}
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 4);
|
||||
|
||||
let mut reader = Reader::new("1.010");
|
||||
assert_eq!(
|
||||
float(&mut reader).unwrap(),
|
||||
Float {
|
||||
value: 1.01,
|
||||
encoded: "1.010".to_string()
|
||||
}
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 5);
|
||||
|
||||
// provide more digits than necessary
|
||||
let mut reader = Reader::new("-0.3333333333333333333");
|
||||
assert_eq!(
|
||||
float(&mut reader).unwrap(),
|
||||
Float {
|
||||
value: -0.3333333333333333,
|
||||
encoded: "-0.3333333333333333333".to_string()
|
||||
}
|
||||
);
|
||||
assert_eq!(reader.state.cursor, 22);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float_error() {
|
||||
let mut reader = Reader::new("");
|
||||
let error = float(&mut reader).err().unwrap();
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("natural")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 1 });
|
||||
assert!(error.recoverable);
|
||||
|
||||
let mut reader = Reader::new("-");
|
||||
let error = float(&mut reader).err().unwrap();
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("natural")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 2 });
|
||||
assert!(error.recoverable);
|
||||
|
||||
let mut reader = Reader::new("1");
|
||||
let error = float(&mut reader).err().unwrap();
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from(".")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 2 });
|
||||
assert!(error.recoverable);
|
||||
|
||||
let mut reader = Reader::new("1x");
|
||||
let error = float(&mut reader).err().unwrap();
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from(".")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 2 });
|
||||
assert!(error.recoverable);
|
||||
|
||||
let mut reader = Reader::new("1.");
|
||||
let error = float(&mut reader).err().unwrap();
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("natural")
|
||||
}
|
||||
);
|
||||
let error = number(&mut reader).err().unwrap();
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 3 });
|
||||
assert!(!error.recoverable);
|
||||
|
||||
let mut reader = Reader::new("1.x");
|
||||
let error = float(&mut reader).err().unwrap();
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("natural")
|
||||
value: String::from("decimal digits")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 3 });
|
||||
assert!(!error.recoverable);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_string_number() {
|
||||
let mut reader = Reader::new("1");
|
||||
assert_eq!(string_number(&mut reader).unwrap(), "1");
|
||||
|
||||
let mut reader = Reader::new("1000000000000000000000");
|
||||
assert_eq!(
|
||||
string_number(&mut reader).unwrap(),
|
||||
"1000000000000000000000"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_number_error() {
|
||||
let mut reader = Reader::new("1.x");
|
||||
let error = string_number(&mut reader).err().unwrap();
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("decimals")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 3 });
|
||||
assert!(!error.recoverable);
|
||||
|
||||
let mut reader = Reader::new("{{");
|
||||
let error = string_number(&mut reader).err().unwrap();
|
||||
assert_eq!(
|
||||
error.inner,
|
||||
ParseError::Expecting {
|
||||
value: String::from("number")
|
||||
}
|
||||
);
|
||||
assert_eq!(error.pos, Pos { line: 1, column: 1 });
|
||||
assert!(error.recoverable);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
use crate::ast::*;
|
||||
use crate::parser::combinators::*;
|
||||
use crate::parser::error::*;
|
||||
use crate::parser::number::{float, integer, natural};
|
||||
use crate::parser::number::{integer, natural, number};
|
||||
use crate::parser::primitives::*;
|
||||
use crate::parser::reader::Reader;
|
||||
use crate::parser::string::*;
|
||||
@ -320,12 +320,8 @@ fn variable_value(reader: &mut Reader) -> ParseResult<VariableValue> {
|
||||
Ok(value) => Ok(VariableValue::Bool(value)),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
|p1| match float(p1) {
|
||||
Ok(value) => Ok(VariableValue::Float(value)),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
|p1| match integer(p1) {
|
||||
Ok(value) => Ok(VariableValue::Integer(value)),
|
||||
|p1| match number(p1) {
|
||||
Ok(value) => Ok(VariableValue::Number(value)),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
|p1| match quoted_template(p1) {
|
||||
@ -542,7 +538,7 @@ mod tests {
|
||||
end: Pos { line: 1, column: 3 },
|
||||
},
|
||||
},
|
||||
value: VariableValue::Integer(1),
|
||||
value: VariableValue::Number(Number::Integer(1)),
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -561,7 +557,7 @@ mod tests {
|
||||
let mut reader = Reader::new("1");
|
||||
assert_eq!(
|
||||
variable_value(&mut reader).unwrap(),
|
||||
VariableValue::Integer(1)
|
||||
VariableValue::Number(Number::Integer(1))
|
||||
);
|
||||
|
||||
let mut reader = Reader::new("toto");
|
||||
|
@ -959,8 +959,7 @@ impl Tokenizable for VariableValue {
|
||||
match self {
|
||||
VariableValue::Null => vec![Token::Keyword("null".to_string())],
|
||||
VariableValue::Bool(v) => vec![Token::Boolean(v.to_string())],
|
||||
VariableValue::Integer(v) => vec![Token::Number(v.to_string())],
|
||||
VariableValue::Float(v) => vec![Token::Number(v.to_string())],
|
||||
VariableValue::Number(v) => vec![Token::Number(v.to_string())],
|
||||
VariableValue::String(v) => v.tokenize(),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user