Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/chyh1990/yaml-rust into c…
Browse files Browse the repository at this point in the history
…hyh1990
  • Loading branch information
chaaz committed Jul 10, 2017
2 parents 629daa2 + d9024de commit 0b7497a
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 64 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "yaml-rust"
version = "0.3.5"
version = "0.3.6"
authors = ["Yuheng Chen <yuhengchen@sensetime.com>"]
homepage = "http://chyh1990.github.io/yaml-rust/"
documentation = "http://chyh1990.github.io/yaml-rust/doc/yaml_rust/"
Expand Down
165 changes: 149 additions & 16 deletions src/emitter.rs
Expand Up @@ -302,17 +302,20 @@ fn need_quotes(string: &str) -> bool {
_ => false,
}
})
|| string == "true"
|| string == "false"
|| string == "null"
|| string == "~"
|| [// http://yaml.org/type/bool.html
"y","Y","yes","Yes","YES","n","N","no","No","NO",
"True", "TRUE", "true", "False", "FALSE", "false",
"on","On","ON","off","Off","OFF",
// http://yaml.org/type/null.html
"null","Null","NULL", "~"
].contains(&string)
|| string.starts_with('.')
|| string.parse::<i64>().is_ok()
|| string.parse::<f64>().is_ok()
}

#[cfg(test)]
mod tests {
mod test {
use super::*;
use YamlLoader;

Expand All @@ -327,15 +330,8 @@ a1:
a2: 4 # i'm comment
a3: [1, 2, 3]
a4:
- - a1
- a2
- [a1, a2]
- 2
- []
- {}
a5: 'single_quoted'
a6: \"double_quoted\"
a7: 你好
'key 1': \"ddd\\\tbbb\"
";


Expand All @@ -346,7 +342,12 @@ a7: 你好
let mut emitter = YamlEmitter::new(&mut writer);
emitter.dump(doc).unwrap();
}
let docs_new = YamlLoader::load_from_str(&s).unwrap();
println!("original:\n{}", s);
println!("emitted:\n{}", writer);
let docs_new = match YamlLoader::load_from_str(&writer) {
Ok(y) => y,
Err(e) => panic!(format!("{}", e))
};
let doc_new = &docs_new[0];

assert_eq!(doc, doc_new);
Expand Down Expand Up @@ -380,7 +381,10 @@ products:
let mut emitter = YamlEmitter::new(&mut writer);
emitter.dump(doc).unwrap();
}
let docs_new = YamlLoader::load_from_str(&s).unwrap();
let docs_new = match YamlLoader::load_from_str(&writer) {
Ok(y) => y,
Err(e) => panic!(format!("{}", e))
};
let doc_new = &docs_new[0];
assert_eq!(doc, doc_new);
}
Expand Down Expand Up @@ -417,7 +421,8 @@ products:
"true": bool key
"{}": empty hash key
x: test
y: string with spaces"#;
"y": "can't avoid quoting here"
z: string with spaces"#;

let docs = YamlLoader::load_from_str(&s).unwrap();
let doc = &docs[0];
Expand All @@ -430,6 +435,64 @@ y: string with spaces"#;
assert_eq!(s, writer, "actual:\n\n{}\n", writer);
}

#[test]
fn emit_quoted_bools() {
let input = r#"---
string0: yes
string1: no
string2: "true"
string3: "false"
string4: "~"
null0: ~
[true, false]: real_bools
[True, TRUE, False, FALSE, y,Y,yes,Yes,YES,n,N,no,No,NO,on,On,ON,off,Off,OFF]: false_bools
bool0: true
bool1: false"#;
let expected = r#"---
string0: "yes"
string1: "no"
string2: "true"
string3: "false"
string4: "~"
null0: ~
? - true
- false
: real_bools
? - "True"
- "TRUE"
- "False"
- "FALSE"
- "y"
- "Y"
- "yes"
- "Yes"
- "YES"
- "n"
- "N"
- "no"
- "No"
- "NO"
- "on"
- "On"
- "ON"
- "off"
- "Off"
- "OFF"
: false_bools
bool0: true
bool1: false"#;

let docs = YamlLoader::load_from_str(&input).unwrap();
let doc = &docs[0];
let mut writer = String::new();
{
let mut emitter = YamlEmitter::new(&mut writer);
emitter.dump(doc).unwrap();
}

assert_eq!(expected, writer, "actual:\n\n{}\n", writer);
}

#[test]
fn test_empty_and_nested() {
test_empty_and_nested_flag(false)
Expand Down Expand Up @@ -471,4 +534,74 @@ e:

assert_eq!(s, writer);
}

#[test]
fn test_nested_arrays() {
let s = r#"---
a:
- b
- - c
- d
- - e
- f"#;

let docs = YamlLoader::load_from_str(&s).unwrap();
let doc = &docs[0];
let mut writer = String::new();
{
let mut emitter = YamlEmitter::new(&mut writer);
emitter.dump(doc).unwrap();
}
println!("original:\n{}", s);
println!("emitted:\n{}", writer);

assert_eq!(s, writer);
}

#[test]
fn test_deeply_nested_arrays() {
let s = r#"---
a:
- b
- - c
- d
- - e
- - f
- - e"#;

let docs = YamlLoader::load_from_str(&s).unwrap();
let doc = &docs[0];
let mut writer = String::new();
{
let mut emitter = YamlEmitter::new(&mut writer);
emitter.dump(doc).unwrap();
}
println!("original:\n{}", s);
println!("emitted:\n{}", writer);

assert_eq!(s, writer);
}

#[test]
fn test_nested_hashes() {
let s = r#"---
a:
b:
c:
d:
e: f"#;

let docs = YamlLoader::load_from_str(&s).unwrap();
let doc = &docs[0];
let mut writer = String::new();
{
let mut emitter = YamlEmitter::new(&mut writer);
emitter.dump(doc).unwrap();
}
println!("original:\n{}", s);
println!("emitted:\n{}", writer);

assert_eq!(s, writer);
}

}
79 changes: 44 additions & 35 deletions src/parser.rs
Expand Up @@ -76,22 +76,20 @@ pub struct Parser<T> {


pub trait EventReceiver {
fn on_event(&mut self, ev: &Event);
fn on_event(&mut self, ev: Event);
}


pub trait MarkedEventReceiver {
fn on_event(&mut self, ev: &Event, _mark: Marker);
fn on_event(&mut self, ev: Event, _mark: Marker);
}

impl<R: EventReceiver> MarkedEventReceiver for R {
fn on_event(&mut self, ev: &Event, _mark: Marker) {
fn on_event(&mut self, ev: Event, _mark: Marker) {
self.on_event(ev)
}
}



pub type ParseResult = Result<(Event, Marker), ScanError>;

impl<T: Iterator<Item=char>> Parser<T> {
Expand Down Expand Up @@ -136,102 +134,113 @@ impl<T: Iterator<Item=char>> Parser<T> {
self.states.push(state);
}

fn parse<R: MarkedEventReceiver>(&mut self, recv: &mut R)
-> Result<Event, ScanError> {
fn parse(&mut self) -> ParseResult {
if self.state == State::End {
return Ok(Event::StreamEnd);
return Ok((Event::StreamEnd, self.scanner.mark()));
}
let (ev, mark) = try!(self.state_machine());
// println!("EV {:?}", ev);
recv.on_event(&ev, mark);
Ok(ev)
Ok((ev, mark))
}

pub fn load<R: MarkedEventReceiver>(&mut self, recv: &mut R, multi: bool)
-> Result<(), ScanError> {
if !self.scanner.stream_started() {
let ev = try!(self.parse(recv));
let (ev, mark) = try!(self.parse());
assert_eq!(ev, Event::StreamStart);
recv.on_event(ev, mark);
}

if self.scanner.stream_ended() {
// XXX has parsed?
recv.on_event(&Event::StreamEnd, self.scanner.mark());
recv.on_event(Event::StreamEnd, self.scanner.mark());
return Ok(());
}
loop {
let ev = try!(self.parse(recv));
let (ev, mark) = try!(self.parse());
if ev == Event::StreamEnd {
recv.on_event(&Event::StreamEnd, self.scanner.mark());
recv.on_event(ev, mark);
return Ok(());
}
// clear anchors before a new document
self.anchors.clear();
try!(self.load_document(&ev, recv));
try!(self.load_document(ev, mark, recv));
if !multi {
break;
}
}
Ok(())
}

fn load_document<R: MarkedEventReceiver>(&mut self, first_ev: &Event, recv: &mut R)
fn load_document<R: MarkedEventReceiver>(&mut self, first_ev: Event, mark: Marker, recv: &mut R)
-> Result<(), ScanError> {
assert_eq!(first_ev, &Event::DocumentStart);
assert_eq!(first_ev, Event::DocumentStart);
recv.on_event(first_ev, mark);

let ev = try!(self.parse(recv));
try!(self.load_node(&ev, recv));
let (ev, mark) = try!(self.parse());
try!(self.load_node(ev, mark, recv));

// DOCUMENT-END is expected.
let ev = try!(self.parse(recv));
let (ev, mark) = try!(self.parse());
assert_eq!(ev, Event::DocumentEnd);
recv.on_event(ev, mark);

Ok(())
}

fn load_node<R: MarkedEventReceiver>(&mut self, first_ev: &Event, recv: &mut R)
fn load_node<R: MarkedEventReceiver>(&mut self, first_ev: Event, mark: Marker, recv: &mut R)
-> Result<(), ScanError> {
match *first_ev {
match first_ev {
Event::Alias(..) | Event::Scalar(..) => {
recv.on_event(first_ev, mark);
Ok(())
},
Event::SequenceStart(_) => {
self.load_sequence(first_ev, recv)
recv.on_event(first_ev, mark);
self.load_sequence(recv)
},
Event::MappingStart(_) => {
self.load_mapping(first_ev, recv)
recv.on_event(first_ev, mark);
self.load_mapping(recv)
},
_ => { println!("UNREACHABLE EVENT: {:?}", first_ev);
unreachable!(); }
}
}

fn load_mapping<R: MarkedEventReceiver>(&mut self, _first_ev: &Event, recv: &mut R)
fn load_mapping<R: MarkedEventReceiver>(&mut self, recv: &mut R)
-> Result<(), ScanError> {
let mut ev = try!(self.parse(recv));
while ev != Event::MappingEnd {
let (mut key_ev, mut key_mark) = try!(self.parse());
while key_ev != Event::MappingEnd {
// key
try!(self.load_node(&ev, recv));
try!(self.load_node(key_ev, key_mark, recv));

// value
ev = try!(self.parse(recv));
try!(self.load_node(&ev, recv));
let (ev, mark) = try!(self.parse());
try!(self.load_node(ev, mark, recv));

// next event
ev = try!(self.parse(recv));
let (ev, mark) = try!(self.parse());
key_ev = ev;
key_mark = mark;

}
recv.on_event(key_ev, key_mark);
Ok(())
}

fn load_sequence<R: MarkedEventReceiver>(&mut self, _first_ev: &Event, recv: &mut R)
fn load_sequence<R: MarkedEventReceiver>(&mut self, recv: &mut R)
-> Result<(), ScanError> {
let mut ev = try!(self.parse(recv));
let (mut ev, mut mark) = try!(self.parse());
while ev != Event::SequenceEnd {
try!(self.load_node(&ev, recv));
try!(self.load_node(ev, mark, recv));

// next event
ev = try!(self.parse(recv));
let (next_ev, next_mark) = try!(self.parse());
ev = next_ev;
mark = next_mark;
}
recv.on_event(ev, mark);
Ok(())
}

Expand Down

0 comments on commit 0b7497a

Please sign in to comment.