2015-05-24 06:27:42 +00:00
|
|
|
use std::collections::{HashMap, BTreeMap};
|
|
|
|
use std::string;
|
2015-05-24 17:34:18 +00:00
|
|
|
use regex::Regex;
|
2015-05-24 06:27:42 +00:00
|
|
|
|
2015-05-24 17:34:18 +00:00
|
|
|
#[derive(Clone, PartialEq, PartialOrd, Debug, Eq, Ord)]
|
2015-05-24 06:27:42 +00:00
|
|
|
pub enum Yaml {
|
|
|
|
I64(i64),
|
2015-05-24 17:34:18 +00:00
|
|
|
//U64(u64),
|
|
|
|
//F64(f64),
|
2015-05-24 06:27:42 +00:00
|
|
|
String(string::String),
|
|
|
|
Boolean(bool),
|
|
|
|
Array(self::Array),
|
|
|
|
Hash(self::Hash),
|
|
|
|
Null,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type Array = Vec<Yaml>;
|
2015-05-24 17:34:18 +00:00
|
|
|
pub type Hash = BTreeMap<Yaml, Yaml>;
|
2015-05-24 06:27:42 +00:00
|
|
|
|
|
|
|
/// The errors that can arise while parsing a YAML stream.
|
|
|
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
|
|
|
pub enum ErrorCode {
|
|
|
|
InvalidSyntax,
|
|
|
|
InvalidNumber,
|
|
|
|
EOFWhileParsingObject,
|
|
|
|
EOFWhileParsingArray,
|
|
|
|
EOFWhileParsingValue,
|
|
|
|
EOFWhileParsingString,
|
|
|
|
KeyMustBeAString,
|
|
|
|
ExpectedColon,
|
|
|
|
TrailingCharacters,
|
|
|
|
TrailingComma,
|
|
|
|
InvalidEscape,
|
|
|
|
InvalidUnicodeCodePoint,
|
|
|
|
LoneLeadingSurrogateInHexEscape,
|
|
|
|
UnexpectedEndOfHexEscape,
|
|
|
|
UnrecognizedHex,
|
|
|
|
NotFourDigit,
|
|
|
|
NotUtf8,
|
|
|
|
}
|
2015-05-24 17:34:18 +00:00
|
|
|
|
|
|
|
macro_rules! define_as (
|
|
|
|
($name:ident, $t:ident, $yt:ident) => (
|
|
|
|
pub fn $name(&self) -> Option<$t> {
|
|
|
|
match *self {
|
|
|
|
Yaml::$yt(v) => Some(v),
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
macro_rules! define_as_ref (
|
|
|
|
($name:ident, $t:ty, $yt:ident) => (
|
|
|
|
pub fn $name(&self) -> Option<$t> {
|
|
|
|
match *self {
|
|
|
|
Yaml::$yt(ref v) => Some(v),
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
// these regex are from libyaml-rust project
|
|
|
|
macro_rules! regex(
|
|
|
|
($s:expr) => (Regex::new($s).unwrap());
|
|
|
|
);
|
|
|
|
impl Yaml {
|
|
|
|
define_as!(as_i64, i64, I64);
|
|
|
|
define_as!(as_bool, bool, Boolean);
|
|
|
|
|
|
|
|
define_as_ref!(as_str, &str, String);
|
|
|
|
define_as_ref!(as_hash, &Hash, Hash);
|
|
|
|
define_as_ref!(as_vec, &Array, Array);
|
|
|
|
|
|
|
|
pub fn is_null(&self) -> bool {
|
|
|
|
match *self {
|
|
|
|
Yaml::Null => true,
|
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_f64(&self) -> Option<f64> {
|
|
|
|
// XXX(chenyh) precompile me
|
|
|
|
let float_pattern = regex!(r"^([-+]?)(\.[0-9]+|[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)$");
|
|
|
|
match *self {
|
|
|
|
Yaml::String(ref v) if float_pattern.is_match(v) => {
|
|
|
|
v.parse::<f64>().ok()
|
|
|
|
},
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use parser::Parser;
|
|
|
|
use yaml::Yaml;
|
|
|
|
// #[test]
|
|
|
|
fn test_coerce() {
|
|
|
|
let s = "---
|
|
|
|
a: 1
|
|
|
|
b: 2.2
|
|
|
|
c: [1, 2]
|
|
|
|
";
|
|
|
|
let mut parser = Parser::new(s.chars());
|
|
|
|
let out = parser.load().unwrap();
|
|
|
|
//assert_eq!(out.as_hash().unwrap()[&Yaml::String("a".to_string())].as_i64().unwrap(), 1i64);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|