diff --git a/saphyr/src/scanner.rs b/saphyr/src/scanner.rs index d25ecb8..619e2d9 100644 --- a/saphyr/src/scanner.rs +++ b/saphyr/src/scanner.rs @@ -1294,12 +1294,12 @@ impl> Scanner { } self.lookahead(2); } + self.lookahead(1); match self.ch() { '\'' if single => { break; }, '"' if !single => { break; }, _ => {} } - self.lookahead(1); // Consume blank characters. while is_blank(self.ch()) || is_break(self.ch()) { diff --git a/saphyr/src/yaml.rs b/saphyr/src/yaml.rs index b8d8163..d745dc6 100644 --- a/saphyr/src/yaml.rs +++ b/saphyr/src/yaml.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use std::ops::Index; use std::string; use std::i64; +use std::f64; use std::mem; use std::vec; use parser::*; @@ -54,6 +55,17 @@ pub enum Yaml { pub type Array = Vec; pub type Hash = LinkedHashMap; +// parse f64 as Core schema +// See: https://github.com/chyh1990/yaml-rust/issues/51 +fn parse_f64(v: &str) -> Option { + match v { + ".inf" | ".Inf" | ".INF" | "+.inf" | "+.Inf" | "+.INF" => Some(f64::INFINITY), + "-.inf" | "-.Inf" | "-.INF" => Some(f64::NEG_INFINITY), + ".nan" | "NaN" | ".NAN" => Some(f64::NAN), + _ => v.parse::().ok() + } +} + pub struct YamlLoader { docs: Vec, // states @@ -115,9 +127,9 @@ impl MarkedEventReceiver for YamlLoader { } }, "float" => { - match v.parse::() { - Err(_) => Yaml::BadValue, - Ok(_) => Yaml::Real(v.clone()) + match parse_f64(v) { + Some(_) => Yaml::Real(v.clone()), + None => Yaml::BadValue, } }, "null" => { @@ -256,18 +268,14 @@ impl Yaml { pub fn as_f64(&self) -> Option { match *self { - Yaml::Real(ref v) => { - v.parse::().ok() - }, + Yaml::Real(ref v) => parse_f64(v), _ => None } } pub fn into_f64(self) -> Option { match self { - Yaml::Real(v) => { - v.parse::().ok() - }, + Yaml::Real(ref v) => parse_f64(v), _ => None } } @@ -299,7 +307,7 @@ impl Yaml { "false" => Yaml::Boolean(false), _ if v.parse::().is_ok() => Yaml::Integer(v.parse::().unwrap()), // try parsing as f64 - _ if v.parse::().is_ok() => Yaml::Real(v.to_owned()), + _ if parse_f64(v).is_some() => Yaml::Real(v.to_owned()), _ => Yaml::String(v.to_owned()) } } @@ -322,9 +330,13 @@ impl Index for Yaml { type Output = Yaml; fn index(&self, idx: usize) -> &Yaml { - match self.as_vec() { - Some(v) => v.get(idx).unwrap_or(&BAD_VALUE), - None => &BAD_VALUE + if let Some(v) = self.as_vec() { + v.get(idx).unwrap_or(&BAD_VALUE) + } else if let Some(v) = self.as_hash() { + let key = Yaml::Integer(idx as i64); + v.get(&key).unwrap_or(&BAD_VALUE) + } else { + &BAD_VALUE } } } @@ -356,6 +368,7 @@ impl Iterator for YamlIter { #[cfg(test)] mod test { use yaml::*; + use std::f64; #[test] fn test_coerce() { let s = "--- @@ -525,6 +538,13 @@ a1: &DEFAULT assert!(YamlLoader::load_from_str(&s).is_err()); } + #[test] + fn test_issue_65() { + // See: https://github.com/chyh1990/yaml-rust/issues/65 + let b = "\n\"ll\\\"ll\\\r\n\"ll\\\"ll\\\r\r\r\rU\r\r\rU"; + assert!(YamlLoader::load_from_str(&b).is_err()); + } + #[test] fn test_bad_docstart() { assert!(YamlLoader::load_from_str("---This used to cause an infinite loop").is_ok()); @@ -554,6 +574,9 @@ a1: &DEFAULT - 0xFF - 0o77 - +12345 +- -.INF +- .NAN +- !!float .INF "; let mut out = YamlLoader::load_from_str(&s).unwrap().into_iter(); let mut doc = out.next().unwrap().into_iter(); @@ -575,6 +598,9 @@ a1: &DEFAULT assert_eq!(doc.next().unwrap().into_i64().unwrap(), 255); assert_eq!(doc.next().unwrap().into_i64().unwrap(), 63); assert_eq!(doc.next().unwrap().into_i64().unwrap(), 12345); + assert_eq!(doc.next().unwrap().into_f64().unwrap(), f64::NEG_INFINITY); + assert!(doc.next().unwrap().into_f64().is_some()); + assert_eq!(doc.next().unwrap().into_f64().unwrap(), f64::INFINITY); } #[test] @@ -592,4 +618,17 @@ c: ~ assert_eq!(Some((Yaml::String("c".to_owned()), Yaml::Null)), iter.next()); assert_eq!(None, iter.next()); } + + #[test] + fn test_integer_key() { + let s = " +0: + important: true +1: + important: false +"; + let out = YamlLoader::load_from_str(&s).unwrap(); + let first = out.into_iter().next().unwrap(); + assert_eq!(first[0]["important"].as_bool().unwrap(), true); + } }