717 lines
17 KiB
Rust
717 lines
17 KiB
Rust
#![allow(
|
|
clippy::cast_lossless,
|
|
clippy::cast_possible_wrap,
|
|
clippy::derive_partial_eq_without_eq,
|
|
clippy::similar_names,
|
|
clippy::uninlined_format_args
|
|
)]
|
|
|
|
use indoc::indoc;
|
|
use serde_derive::Deserialize;
|
|
use serde_yaml::{Deserializer, Number, Value};
|
|
use std::collections::BTreeMap;
|
|
use std::fmt::Debug;
|
|
|
|
fn test_de<T>(yaml: &str, expected: &T)
|
|
where
|
|
T: serde::de::DeserializeOwned + PartialEq + Debug,
|
|
{
|
|
let deserialized: T = serde_yaml::from_str(yaml).unwrap();
|
|
assert_eq!(*expected, deserialized);
|
|
|
|
let value: Value = serde_yaml::from_str(yaml).unwrap();
|
|
let deserialized = T::deserialize(&value).unwrap();
|
|
assert_eq!(*expected, deserialized);
|
|
|
|
let deserialized: T = serde_yaml::from_value(value).unwrap();
|
|
assert_eq!(*expected, deserialized);
|
|
|
|
serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
|
|
|
|
let mut deserializer = Deserializer::from_str(yaml);
|
|
let document = deserializer.next().unwrap();
|
|
let deserialized = T::deserialize(document).unwrap();
|
|
assert_eq!(*expected, deserialized);
|
|
assert!(deserializer.next().is_none());
|
|
}
|
|
|
|
fn test_de_no_value<'de, T>(yaml: &'de str, expected: &T)
|
|
where
|
|
T: serde::de::Deserialize<'de> + PartialEq + Debug,
|
|
{
|
|
let deserialized: T = serde_yaml::from_str(yaml).unwrap();
|
|
assert_eq!(*expected, deserialized);
|
|
|
|
serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap();
|
|
serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
|
|
}
|
|
|
|
fn test_de_seed<'de, T, S>(yaml: &'de str, seed: S, expected: &T)
|
|
where
|
|
T: PartialEq + Debug,
|
|
S: serde::de::DeserializeSeed<'de, Value = T>,
|
|
{
|
|
let deserialized: T = seed.deserialize(Deserializer::from_str(yaml)).unwrap();
|
|
assert_eq!(*expected, deserialized);
|
|
|
|
serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap();
|
|
serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn test_borrowed() {
|
|
let yaml = indoc! {"
|
|
- plain nonàscii
|
|
- 'single quoted'
|
|
- \"double quoted\"
|
|
"};
|
|
let expected = vec!["plain nonàscii", "single quoted", "double quoted"];
|
|
test_de_no_value(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_alias() {
|
|
let yaml = indoc! {"
|
|
first:
|
|
&alias
|
|
1
|
|
second:
|
|
*alias
|
|
third: 3
|
|
"};
|
|
let mut expected = BTreeMap::new();
|
|
expected.insert("first".to_owned(), 1);
|
|
expected.insert("second".to_owned(), 1);
|
|
expected.insert("third".to_owned(), 3);
|
|
test_de(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_option() {
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
struct Data {
|
|
a: Option<f64>,
|
|
b: Option<String>,
|
|
c: Option<bool>,
|
|
}
|
|
let yaml = indoc! {"
|
|
b:
|
|
c: true
|
|
"};
|
|
let expected = Data {
|
|
a: None,
|
|
b: None,
|
|
c: Some(true),
|
|
};
|
|
test_de(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_option_alias() {
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
struct Data {
|
|
a: Option<f64>,
|
|
b: Option<String>,
|
|
c: Option<bool>,
|
|
d: Option<f64>,
|
|
e: Option<String>,
|
|
f: Option<bool>,
|
|
}
|
|
let yaml = indoc! {"
|
|
none_f:
|
|
&none_f
|
|
~
|
|
none_s:
|
|
&none_s
|
|
~
|
|
none_b:
|
|
&none_b
|
|
~
|
|
|
|
some_f:
|
|
&some_f
|
|
1.0
|
|
some_s:
|
|
&some_s
|
|
x
|
|
some_b:
|
|
&some_b
|
|
true
|
|
|
|
a: *none_f
|
|
b: *none_s
|
|
c: *none_b
|
|
d: *some_f
|
|
e: *some_s
|
|
f: *some_b
|
|
"};
|
|
let expected = Data {
|
|
a: None,
|
|
b: None,
|
|
c: None,
|
|
d: Some(1.0),
|
|
e: Some("x".to_owned()),
|
|
f: Some(true),
|
|
};
|
|
test_de(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_enum_alias() {
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
enum E {
|
|
A,
|
|
B(u8, u8),
|
|
}
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
struct Data {
|
|
a: E,
|
|
b: E,
|
|
}
|
|
let yaml = indoc! {"
|
|
aref:
|
|
&aref
|
|
A
|
|
bref:
|
|
&bref
|
|
!B
|
|
- 1
|
|
- 2
|
|
|
|
a: *aref
|
|
b: *bref
|
|
"};
|
|
let expected = Data {
|
|
a: E::A,
|
|
b: E::B(1, 2),
|
|
};
|
|
test_de(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_enum_representations() {
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
enum Enum {
|
|
Unit,
|
|
Tuple(i32, i32),
|
|
Struct { x: i32, y: i32 },
|
|
String(String),
|
|
Number(f64),
|
|
}
|
|
|
|
let yaml = indoc! {"
|
|
- Unit
|
|
- 'Unit'
|
|
- !Unit
|
|
- !Unit ~
|
|
- !Unit null
|
|
- !Tuple [0, 0]
|
|
- !Tuple
|
|
- 0
|
|
- 0
|
|
- !Struct {x: 0, y: 0}
|
|
- !Struct
|
|
x: 0
|
|
y: 0
|
|
- !String '...'
|
|
- !String ...
|
|
- !Number 0
|
|
"};
|
|
|
|
let expected = vec![
|
|
Enum::Unit,
|
|
Enum::Unit,
|
|
Enum::Unit,
|
|
Enum::Unit,
|
|
Enum::Unit,
|
|
Enum::Tuple(0, 0),
|
|
Enum::Tuple(0, 0),
|
|
Enum::Struct { x: 0, y: 0 },
|
|
Enum::Struct { x: 0, y: 0 },
|
|
Enum::String("...".to_owned()),
|
|
Enum::String("...".to_owned()),
|
|
Enum::Number(0.0),
|
|
];
|
|
|
|
test_de(yaml, &expected);
|
|
|
|
let yaml = indoc! {"
|
|
- !String
|
|
"};
|
|
let expected = vec![Enum::String(String::new())];
|
|
test_de_no_value(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_number_as_string() {
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
struct Num {
|
|
value: String,
|
|
}
|
|
let yaml = indoc! {"
|
|
# Cannot be represented as u128
|
|
value: 340282366920938463463374607431768211457
|
|
"};
|
|
let expected = Num {
|
|
value: "340282366920938463463374607431768211457".to_owned(),
|
|
};
|
|
test_de_no_value(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_empty_string() {
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
struct Struct {
|
|
empty: String,
|
|
tilde: String,
|
|
}
|
|
let yaml = indoc! {"
|
|
empty:
|
|
tilde: ~
|
|
"};
|
|
let expected = Struct {
|
|
empty: String::new(),
|
|
tilde: "~".to_owned(),
|
|
};
|
|
test_de_no_value(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_i128_big() {
|
|
let expected: i128 = i64::MIN as i128 - 1;
|
|
let yaml = indoc! {"
|
|
-9223372036854775809
|
|
"};
|
|
assert_eq!(expected, serde_yaml::from_str::<i128>(yaml).unwrap());
|
|
|
|
let octal = indoc! {"
|
|
-0o1000000000000000000001
|
|
"};
|
|
assert_eq!(expected, serde_yaml::from_str::<i128>(octal).unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_u128_big() {
|
|
let expected: u128 = u64::MAX as u128 + 1;
|
|
let yaml = indoc! {"
|
|
18446744073709551616
|
|
"};
|
|
assert_eq!(expected, serde_yaml::from_str::<u128>(yaml).unwrap());
|
|
|
|
let octal = indoc! {"
|
|
0o2000000000000000000000
|
|
"};
|
|
assert_eq!(expected, serde_yaml::from_str::<u128>(octal).unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_number_alias_as_string() {
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
struct Num {
|
|
version: String,
|
|
value: String,
|
|
}
|
|
let yaml = indoc! {"
|
|
version: &a 1.10
|
|
value: *a
|
|
"};
|
|
let expected = Num {
|
|
version: "1.10".to_owned(),
|
|
value: "1.10".to_owned(),
|
|
};
|
|
test_de_no_value(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_de_mapping() {
|
|
#[derive(Debug, Deserialize, PartialEq)]
|
|
struct Data {
|
|
pub substructure: serde_yaml::Mapping,
|
|
}
|
|
let yaml = indoc! {"
|
|
substructure:
|
|
a: 'foo'
|
|
b: 'bar'
|
|
"};
|
|
|
|
let mut expected = Data {
|
|
substructure: serde_yaml::Mapping::new(),
|
|
};
|
|
expected.substructure.insert(
|
|
serde_yaml::Value::String("a".to_owned()),
|
|
serde_yaml::Value::String("foo".to_owned()),
|
|
);
|
|
expected.substructure.insert(
|
|
serde_yaml::Value::String("b".to_owned()),
|
|
serde_yaml::Value::String("bar".to_owned()),
|
|
);
|
|
|
|
test_de(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_byte_order_mark() {
|
|
let yaml = "\u{feff}- 0\n";
|
|
let expected = vec![0];
|
|
test_de(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_bomb() {
|
|
#[derive(Debug, Deserialize, PartialEq)]
|
|
struct Data {
|
|
expected: String,
|
|
}
|
|
|
|
// This would deserialize an astronomical number of elements if we were
|
|
// vulnerable.
|
|
let yaml = indoc! {"
|
|
a: &a ~
|
|
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
|
|
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
|
|
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
|
|
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
|
|
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
|
|
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
|
|
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
|
|
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
|
|
j: &j [*i,*i,*i,*i,*i,*i,*i,*i,*i]
|
|
k: &k [*j,*j,*j,*j,*j,*j,*j,*j,*j]
|
|
l: &l [*k,*k,*k,*k,*k,*k,*k,*k,*k]
|
|
m: &m [*l,*l,*l,*l,*l,*l,*l,*l,*l]
|
|
n: &n [*m,*m,*m,*m,*m,*m,*m,*m,*m]
|
|
o: &o [*n,*n,*n,*n,*n,*n,*n,*n,*n]
|
|
p: &p [*o,*o,*o,*o,*o,*o,*o,*o,*o]
|
|
q: &q [*p,*p,*p,*p,*p,*p,*p,*p,*p]
|
|
r: &r [*q,*q,*q,*q,*q,*q,*q,*q,*q]
|
|
s: &s [*r,*r,*r,*r,*r,*r,*r,*r,*r]
|
|
t: &t [*s,*s,*s,*s,*s,*s,*s,*s,*s]
|
|
u: &u [*t,*t,*t,*t,*t,*t,*t,*t,*t]
|
|
v: &v [*u,*u,*u,*u,*u,*u,*u,*u,*u]
|
|
w: &w [*v,*v,*v,*v,*v,*v,*v,*v,*v]
|
|
x: &x [*w,*w,*w,*w,*w,*w,*w,*w,*w]
|
|
y: &y [*x,*x,*x,*x,*x,*x,*x,*x,*x]
|
|
z: &z [*y,*y,*y,*y,*y,*y,*y,*y,*y]
|
|
expected: string
|
|
"};
|
|
|
|
let expected = Data {
|
|
expected: "string".to_owned(),
|
|
};
|
|
|
|
assert_eq!(expected, serde_yaml::from_str::<Data>(yaml).unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_numbers() {
|
|
let cases = [
|
|
("0xF0", "240"),
|
|
("+0xF0", "240"),
|
|
("-0xF0", "-240"),
|
|
("0o70", "56"),
|
|
("+0o70", "56"),
|
|
("-0o70", "-56"),
|
|
("0b10", "2"),
|
|
("+0b10", "2"),
|
|
("-0b10", "-2"),
|
|
("127", "127"),
|
|
("+127", "127"),
|
|
("-127", "-127"),
|
|
(".inf", ".inf"),
|
|
(".Inf", ".inf"),
|
|
(".INF", ".inf"),
|
|
("-.inf", "-.inf"),
|
|
("-.Inf", "-.inf"),
|
|
("-.INF", "-.inf"),
|
|
(".nan", ".nan"),
|
|
(".NaN", ".nan"),
|
|
(".NAN", ".nan"),
|
|
("0.1", "0.1"),
|
|
];
|
|
for &(yaml, expected) in &cases {
|
|
let value = serde_yaml::from_str::<Value>(yaml).unwrap();
|
|
match value {
|
|
Value::Number(number) => assert_eq!(number.to_string(), expected),
|
|
_ => panic!("expected number. input={:?}, result={:?}", yaml, value),
|
|
}
|
|
}
|
|
|
|
// NOT numbers.
|
|
let cases = [
|
|
"0127", "+0127", "-0127", "++.inf", "+-.inf", "++1", "+-1", "-+1", "--1", "0x+1", "0x-1",
|
|
"-0x+1", "-0x-1", "++0x1", "+-0x1", "-+0x1", "--0x1",
|
|
];
|
|
for yaml in &cases {
|
|
let value = serde_yaml::from_str::<Value>(yaml).unwrap();
|
|
match value {
|
|
Value::String(string) => assert_eq!(string, *yaml),
|
|
_ => panic!("expected string. input={:?}, result={:?}", yaml, value),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_nan() {
|
|
// There is no negative NaN in YAML.
|
|
assert!(serde_yaml::from_str::<f32>(".nan")
|
|
.unwrap()
|
|
.is_sign_positive());
|
|
assert!(serde_yaml::from_str::<f64>(".nan")
|
|
.unwrap()
|
|
.is_sign_positive());
|
|
}
|
|
|
|
#[test]
|
|
fn test_stateful() {
|
|
struct Seed(i64);
|
|
|
|
impl<'de> serde::de::DeserializeSeed<'de> for Seed {
|
|
type Value = i64;
|
|
fn deserialize<D>(self, deserializer: D) -> Result<i64, D::Error>
|
|
where
|
|
D: serde::de::Deserializer<'de>,
|
|
{
|
|
struct Visitor(i64);
|
|
impl<'de> serde::de::Visitor<'de> for Visitor {
|
|
type Value = i64;
|
|
|
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
write!(formatter, "an integer")
|
|
}
|
|
|
|
fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<i64, E> {
|
|
Ok(v * self.0)
|
|
}
|
|
|
|
fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<i64, E> {
|
|
Ok(v as i64 * self.0)
|
|
}
|
|
}
|
|
|
|
deserializer.deserialize_any(Visitor(self.0))
|
|
}
|
|
}
|
|
|
|
let cases = [("3", 5, 15), ("6", 7, 42), ("-5", 9, -45)];
|
|
for &(yaml, seed, expected) in &cases {
|
|
test_de_seed(yaml, Seed(seed), &expected);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_ignore_tag() {
|
|
#[derive(Deserialize, Debug, PartialEq)]
|
|
struct Data {
|
|
struc: Struc,
|
|
tuple: Tuple,
|
|
newtype: Newtype,
|
|
map: BTreeMap<char, usize>,
|
|
vec: Vec<usize>,
|
|
}
|
|
|
|
#[derive(Deserialize, Debug, PartialEq)]
|
|
struct Struc {
|
|
x: usize,
|
|
}
|
|
|
|
#[derive(Deserialize, Debug, PartialEq)]
|
|
struct Tuple(usize, usize);
|
|
|
|
#[derive(Deserialize, Debug, PartialEq)]
|
|
struct Newtype(usize);
|
|
|
|
let yaml = indoc! {"
|
|
struc: !wat
|
|
x: 0
|
|
tuple: !wat
|
|
- 0
|
|
- 0
|
|
newtype: !wat 0
|
|
map: !wat
|
|
x: 0
|
|
vec: !wat
|
|
- 0
|
|
"};
|
|
|
|
let expected = Data {
|
|
struc: Struc { x: 0 },
|
|
tuple: Tuple(0, 0),
|
|
newtype: Newtype(0),
|
|
map: {
|
|
let mut map = BTreeMap::new();
|
|
map.insert('x', 0);
|
|
map
|
|
},
|
|
vec: vec![0],
|
|
};
|
|
|
|
test_de(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_no_required_fields() {
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
pub struct NoRequiredFields {
|
|
optional: Option<usize>,
|
|
}
|
|
|
|
for document in ["", "# comment\n"] {
|
|
let expected = NoRequiredFields { optional: None };
|
|
let deserialized: NoRequiredFields = serde_yaml::from_str(document).unwrap();
|
|
assert_eq!(expected, deserialized);
|
|
|
|
let expected = Vec::<String>::new();
|
|
let deserialized: Vec<String> = serde_yaml::from_str(document).unwrap();
|
|
assert_eq!(expected, deserialized);
|
|
|
|
let expected = BTreeMap::new();
|
|
let deserialized: BTreeMap<char, usize> = serde_yaml::from_str(document).unwrap();
|
|
assert_eq!(expected, deserialized);
|
|
|
|
let expected = None;
|
|
let deserialized: Option<String> = serde_yaml::from_str(document).unwrap();
|
|
assert_eq!(expected, deserialized);
|
|
|
|
let expected = Value::Null;
|
|
let deserialized: Value = serde_yaml::from_str(document).unwrap();
|
|
assert_eq!(expected, deserialized);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_empty_scalar() {
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
struct Struct<T> {
|
|
thing: T,
|
|
}
|
|
|
|
let yaml = "thing:\n";
|
|
let expected = Struct {
|
|
thing: serde_yaml::Sequence::new(),
|
|
};
|
|
test_de(yaml, &expected);
|
|
|
|
let expected = Struct {
|
|
thing: serde_yaml::Mapping::new(),
|
|
};
|
|
test_de(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_python_safe_dump() {
|
|
#[derive(Deserialize, PartialEq, Debug)]
|
|
struct Frob {
|
|
foo: u32,
|
|
}
|
|
|
|
// This matches output produced by PyYAML's `yaml.safe_dump` when using the
|
|
// default_style parameter.
|
|
//
|
|
// >>> import yaml
|
|
// >>> d = {"foo": 7200}
|
|
// >>> print(yaml.safe_dump(d, default_style="|"))
|
|
// "foo": !!int |-
|
|
// 7200
|
|
//
|
|
let yaml = indoc! {r#"
|
|
"foo": !!int |-
|
|
7200
|
|
"#};
|
|
|
|
let expected = Frob { foo: 7200 };
|
|
test_de(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_tag_resolution() {
|
|
// https://yaml.org/spec/1.2.2/#1032-tag-resolution
|
|
let yaml = indoc! {"
|
|
- null
|
|
- Null
|
|
- NULL
|
|
- ~
|
|
-
|
|
- true
|
|
- True
|
|
- TRUE
|
|
- false
|
|
- False
|
|
- FALSE
|
|
- y
|
|
- Y
|
|
- yes
|
|
- Yes
|
|
- YES
|
|
- n
|
|
- N
|
|
- no
|
|
- No
|
|
- NO
|
|
- on
|
|
- On
|
|
- ON
|
|
- off
|
|
- Off
|
|
- OFF
|
|
"};
|
|
|
|
let expected = vec![
|
|
Value::Null,
|
|
Value::Null,
|
|
Value::Null,
|
|
Value::Null,
|
|
Value::Null,
|
|
Value::Bool(true),
|
|
Value::Bool(true),
|
|
Value::Bool(true),
|
|
Value::Bool(false),
|
|
Value::Bool(false),
|
|
Value::Bool(false),
|
|
Value::String("y".to_owned()),
|
|
Value::String("Y".to_owned()),
|
|
Value::String("yes".to_owned()),
|
|
Value::String("Yes".to_owned()),
|
|
Value::String("YES".to_owned()),
|
|
Value::String("n".to_owned()),
|
|
Value::String("N".to_owned()),
|
|
Value::String("no".to_owned()),
|
|
Value::String("No".to_owned()),
|
|
Value::String("NO".to_owned()),
|
|
Value::String("on".to_owned()),
|
|
Value::String("On".to_owned()),
|
|
Value::String("ON".to_owned()),
|
|
Value::String("off".to_owned()),
|
|
Value::String("Off".to_owned()),
|
|
Value::String("OFF".to_owned()),
|
|
];
|
|
|
|
test_de(yaml, &expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_number() {
|
|
let n = "111".parse::<Number>().unwrap();
|
|
assert_eq!(n, Number::from(111));
|
|
|
|
let n = "-111".parse::<Number>().unwrap();
|
|
assert_eq!(n, Number::from(-111));
|
|
|
|
let n = "-1.1".parse::<Number>().unwrap();
|
|
assert_eq!(n, Number::from(-1.1));
|
|
|
|
let n = ".nan".parse::<Number>().unwrap();
|
|
assert_eq!(n, Number::from(f64::NAN));
|
|
assert!(n.as_f64().unwrap().is_sign_positive());
|
|
|
|
let n = ".inf".parse::<Number>().unwrap();
|
|
assert_eq!(n, Number::from(f64::INFINITY));
|
|
|
|
let n = "-.inf".parse::<Number>().unwrap();
|
|
assert_eq!(n, Number::from(f64::NEG_INFINITY));
|
|
|
|
let err = "null".parse::<Number>().unwrap_err();
|
|
assert_eq!(err.to_string(), "failed to parse YAML number");
|
|
|
|
let err = " 1 ".parse::<Number>().unwrap_err();
|
|
assert_eq!(err.to_string(), "failed to parse YAML number");
|
|
}
|