Fix nested arrays, emit compact in-line

This commit is contained in:
Charlie Ozinga 2017-05-11 23:29:41 -06:00
parent ff8572352d
commit 06c9b22357
2 changed files with 70 additions and 44 deletions

View file

@ -3,6 +3,15 @@ use std::convert::From;
use std::error::Error; use std::error::Error;
use yaml::{Hash, Yaml}; use yaml::{Hash, Yaml};
/// If the emitter should output in 'compact inline notation' form, as
/// described for block
/// [sequences](http://www.yaml.org/spec/1.2/spec.html#id2797382) and
/// [mappings](http://www.yaml.org/spec/1.2/spec.html#id2798057). In
/// this form, blocks cannot have any properties (such as anchors or
/// tags), which should be OK, because this emitter doesn't (currently)
/// emit those anyways.
pub const COMPACT: bool = true;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum EmitError { pub enum EmitError {
FmtError(fmt::Error), FmtError(fmt::Error),
@ -174,16 +183,16 @@ impl<'a> YamlEmitter<'a> {
if v.is_empty() { if v.is_empty() {
try!(write!(self.writer, "[]")); try!(write!(self.writer, "[]"));
} else { } else {
self.level += 1;
for (cnt, x) in v.iter().enumerate() { for (cnt, x) in v.iter().enumerate() {
if cnt > 0 { if cnt > 0 {
try!(write!(self.writer, "\n")); try!(write!(self.writer, "\n"));
}
try!(self.write_indent()); try!(self.write_indent());
self.level += 1;
try!(write!(self.writer, "- "));
try!(self.emit_node(x));
self.level -= 1;
} }
try!(write!(self.writer, "-"));
try!(self.emit_val(true, x));
}
self.level -= 1;
} }
Ok(()) Ok(())
} }
@ -203,51 +212,57 @@ impl<'a> YamlEmitter<'a> {
try!(self.write_indent()); try!(self.write_indent());
} }
if complex_key { if complex_key {
try!(write!(self.writer, "? ")); try!(write!(self.writer, "?"));
self.level += 1; try!(self.emit_val(true, k));
try!(self.emit_node(k));
self.level -= 1;
try!(write!(self.writer, "\n")); try!(write!(self.writer, "\n"));
try!(self.write_indent()); try!(self.write_indent());
try!(write!(self.writer, ":"));
try!(self.emit_val(true, v));
} else { } else {
try!(self.emit_node(k)); try!(self.emit_node(k));
} try!(write!(self.writer, ":"));
match *v { try!(self.emit_val(false, v));
Yaml::Array(ref v) => {
if complex_key { self.level += 1; }
if v.is_empty() {
try!(write!(self.writer, ": "));
} else {
try!(write!(self.writer, ":\n"));
}
try!(self.emit_array(v));
if complex_key { self.level -= 1; }
}
Yaml::Hash(ref h) => {
if complex_key { self.level += 1; }
if h.is_empty() {
try!(write!(self.writer, ": "));
} else {
try!(write!(self.writer, ":\n"));
self.level += 1;
try!(self.write_indent());
self.level -= 1;
}
try!(self.emit_hash(h));
if complex_key { self.level -= 1; }
}
_ => {
if complex_key { self.level += 1; }
try!(write!(self.writer, ": "));
try!(self.emit_node(v));
if complex_key { self.level -= 1; }
}
} }
} }
self.level -= 1; self.level -= 1;
} }
Ok(()) Ok(())
} }
/// Emit a yaml as a hash or array value: i.e., which should appear
/// following a ":" or "-", either after a space, or on a new line.
/// If `inline` is true, then the preceeding characters are distinct
/// and short enough to respects the COMPACT constant.
fn emit_val(&mut self, inline: bool, val: &Yaml) -> EmitResult {
match *val {
Yaml::Array(ref v) => {
if (inline && COMPACT) || v.is_empty() {
try!(write!(self.writer, " "));
} else {
try!(write!(self.writer, "\n"));
self.level += 1;
try!(self.write_indent());
self.level -= 1;
}
self.emit_array(v)
},
Yaml::Hash(ref h) => {
if (inline && COMPACT) || h.is_empty() {
try!(write!(self.writer, " "));
} else {
try!(write!(self.writer, "\n"));
self.level += 1;
try!(self.write_indent());
self.level -= 1;
}
self.emit_hash(h)
},
_ => {
try!(write!(self.writer, " "));
self.emit_node(val)
}
}
}
} }
/// Check if the string requires quoting. /// Check if the string requires quoting.
@ -406,15 +421,24 @@ y: string with spaces"#;
#[test] #[test]
fn test_empty_and_nested() { fn test_empty_and_nested() {
let s = r#"--- let s = if COMPACT { r#"---
a: a:
b: b:
c: hello c: hello
d: {} d: {}
e: e:
- f - f
- g - g
- h: []"#; - h: []"# } else { r#"---
a:
b:
c: hello
d: {}
e:
- f
- g
-
h: []"# };
let docs = YamlLoader::load_from_str(&s).unwrap(); let docs = YamlLoader::load_from_str(&s).unwrap();
let doc = &docs[0]; let doc = &docs[0];

View file

@ -136,6 +136,8 @@ fn test_mapvec_legal() {
// - 6 // - 6
// ``` // ```
println!("{}", out_str);
YamlLoader::load_from_str(&out_str).unwrap(); YamlLoader::load_from_str(&out_str).unwrap();
} }