Add alias deserialize support
This commit is contained in:
parent
de8e94ab34
commit
071d338e0e
2 changed files with 55 additions and 15 deletions
|
@ -2,6 +2,7 @@ language: rust
|
||||||
rust:
|
rust:
|
||||||
- 1.0.0
|
- 1.0.0
|
||||||
- 1.1.0
|
- 1.1.0
|
||||||
|
- 1.5.0
|
||||||
- nightly
|
- nightly
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
|
|
|
@ -53,8 +53,10 @@ pub type Hash = BTreeMap<Yaml, Yaml>;
|
||||||
pub struct YamlLoader {
|
pub struct YamlLoader {
|
||||||
docs: Vec<Yaml>,
|
docs: Vec<Yaml>,
|
||||||
// states
|
// states
|
||||||
doc_stack: Vec<Yaml>,
|
// (current node, anchor_id) tuple
|
||||||
|
doc_stack: Vec<(Yaml, usize)>,
|
||||||
key_stack: Vec<Yaml>,
|
key_stack: Vec<Yaml>,
|
||||||
|
anchor_map: BTreeMap<usize, Yaml>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventReceiver for YamlLoader {
|
impl EventReceiver for YamlLoader {
|
||||||
|
@ -68,19 +70,19 @@ impl EventReceiver for YamlLoader {
|
||||||
match self.doc_stack.len() {
|
match self.doc_stack.len() {
|
||||||
// empty document
|
// empty document
|
||||||
0 => self.docs.push(Yaml::BadValue),
|
0 => self.docs.push(Yaml::BadValue),
|
||||||
1 => self.docs.push(self.doc_stack.pop().unwrap()),
|
1 => self.docs.push(self.doc_stack.pop().unwrap().0),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Event::SequenceStart(_) => {
|
Event::SequenceStart(aid) => {
|
||||||
self.doc_stack.push(Yaml::Array(Vec::new()));
|
self.doc_stack.push((Yaml::Array(Vec::new()), aid));
|
||||||
},
|
},
|
||||||
Event::SequenceEnd => {
|
Event::SequenceEnd => {
|
||||||
let node = self.doc_stack.pop().unwrap();
|
let node = self.doc_stack.pop().unwrap();
|
||||||
self.insert_new_node(node);
|
self.insert_new_node(node);
|
||||||
},
|
},
|
||||||
Event::MappingStart(_) => {
|
Event::MappingStart(aid) => {
|
||||||
self.doc_stack.push(Yaml::Hash(Hash::new()));
|
self.doc_stack.push((Yaml::Hash(Hash::new()), aid));
|
||||||
self.key_stack.push(Yaml::BadValue);
|
self.key_stack.push(Yaml::BadValue);
|
||||||
},
|
},
|
||||||
Event::MappingEnd => {
|
Event::MappingEnd => {
|
||||||
|
@ -88,7 +90,7 @@ impl EventReceiver for YamlLoader {
|
||||||
let node = self.doc_stack.pop().unwrap();
|
let node = self.doc_stack.pop().unwrap();
|
||||||
self.insert_new_node(node);
|
self.insert_new_node(node);
|
||||||
},
|
},
|
||||||
Event::Scalar(ref v, style, _, ref tag) => {
|
Event::Scalar(ref v, style, aid, ref tag) => {
|
||||||
let node = if style != TScalarStyle::Plain {
|
let node = if style != TScalarStyle::Plain {
|
||||||
Yaml::String(v.clone())
|
Yaml::String(v.clone())
|
||||||
} else {
|
} else {
|
||||||
|
@ -133,11 +135,14 @@ impl EventReceiver for YamlLoader {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.insert_new_node(node);
|
self.insert_new_node((node, aid));
|
||||||
},
|
},
|
||||||
Event::Alias(id) => {
|
Event::Alias(id) => {
|
||||||
// XXX(chenyh): how to handle alias?
|
let n = match self.anchor_map.get(&id) {
|
||||||
self.insert_new_node(Yaml::Alias(id));
|
Some(v) => v.clone(),
|
||||||
|
None => Yaml::BadValue,
|
||||||
|
};
|
||||||
|
self.insert_new_node((n, 0));
|
||||||
}
|
}
|
||||||
_ => { /* ignore */ }
|
_ => { /* ignore */ }
|
||||||
}
|
}
|
||||||
|
@ -146,21 +151,25 @@ impl EventReceiver for YamlLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl YamlLoader {
|
impl YamlLoader {
|
||||||
fn insert_new_node(&mut self, node: Yaml) {
|
fn insert_new_node(&mut self, node: (Yaml, usize)) {
|
||||||
|
// valid anchor id starts from 1
|
||||||
|
if node.1 > 0 {
|
||||||
|
self.anchor_map.insert(node.1, node.0.clone());
|
||||||
|
}
|
||||||
if !self.doc_stack.is_empty() {
|
if !self.doc_stack.is_empty() {
|
||||||
let parent = self.doc_stack.last_mut().unwrap();
|
let parent = self.doc_stack.last_mut().unwrap();
|
||||||
match *parent {
|
match *parent {
|
||||||
Yaml::Array(ref mut v) => v.push(node),
|
(Yaml::Array(ref mut v), _) => v.push(node.0),
|
||||||
Yaml::Hash(ref mut h) => {
|
(Yaml::Hash(ref mut h), _) => {
|
||||||
let mut cur_key = self.key_stack.last_mut().unwrap();
|
let mut cur_key = self.key_stack.last_mut().unwrap();
|
||||||
// current node is a key
|
// current node is a key
|
||||||
if cur_key.is_badvalue() {
|
if cur_key.is_badvalue() {
|
||||||
*cur_key = node;
|
*cur_key = node.0;
|
||||||
// current node is a value
|
// current node is a value
|
||||||
} else {
|
} else {
|
||||||
let mut newkey = Yaml::BadValue;
|
let mut newkey = Yaml::BadValue;
|
||||||
mem::swap(&mut newkey, cur_key);
|
mem::swap(&mut newkey, cur_key);
|
||||||
h.insert(newkey, node);
|
h.insert(newkey, node.0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -175,6 +184,7 @@ impl YamlLoader {
|
||||||
docs: Vec::new(),
|
docs: Vec::new(),
|
||||||
doc_stack: Vec::new(),
|
doc_stack: Vec::new(),
|
||||||
key_stack: Vec::new(),
|
key_stack: Vec::new(),
|
||||||
|
anchor_map: BTreeMap::new(),
|
||||||
};
|
};
|
||||||
let mut parser = Parser::new(source.chars());
|
let mut parser = Parser::new(source.chars());
|
||||||
try!(parser.load(&mut loader, true));
|
try!(parser.load(&mut loader, true));
|
||||||
|
@ -327,6 +337,35 @@ a7: 你好
|
||||||
assert_eq!(out.len(), 3);
|
assert_eq!(out.len(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_anchor() {
|
||||||
|
let s =
|
||||||
|
"
|
||||||
|
a1: &DEFAULT
|
||||||
|
b1: 4
|
||||||
|
b2: d
|
||||||
|
a2: *DEFAULT
|
||||||
|
";
|
||||||
|
let out = YamlLoader::load_from_str(&s).unwrap();
|
||||||
|
let doc = &out[0];
|
||||||
|
assert_eq!(doc["a2"]["b1"].as_i64().unwrap(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bad_anchor() {
|
||||||
|
let s =
|
||||||
|
"
|
||||||
|
a1: &DEFAULT
|
||||||
|
b1: 4
|
||||||
|
b2: *DEFAULT
|
||||||
|
";
|
||||||
|
let out = YamlLoader::load_from_str(&s).unwrap();
|
||||||
|
let doc = &out[0];
|
||||||
|
assert_eq!(doc["a1"]["b2"], Yaml::BadValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_plain_datatype() {
|
fn test_plain_datatype() {
|
||||||
let s =
|
let s =
|
||||||
|
|
Loading…
Reference in a new issue