From ff8572352dc3dbd403a65212673fd85606eeaa7d Mon Sep 17 00:00:00 2001 From: Charlie Ozinga Date: Thu, 11 May 2017 12:36:38 -0600 Subject: [PATCH] Rebased and resolved conflicts with the following: https://github.com/chyh1990/yaml-rust/pull/66 https://github.com/chyh1990/yaml-rust/pull/62 (closed in favor of 66) --- saphyr/src/emitter.rs | 68 +++++++++++---------------------------- saphyr/tests/spec_test.rs | 66 +++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 49 deletions(-) diff --git a/saphyr/src/emitter.rs b/saphyr/src/emitter.rs index 45f2024..ba0bf7e 100644 --- a/saphyr/src/emitter.rs +++ b/saphyr/src/emitter.rs @@ -132,48 +132,6 @@ impl<'a> YamlEmitter<'a> { Ok(()) } - fn emit_node_compact(&mut self, node: &Yaml) -> EmitResult { - match *node { - Yaml::Array(ref v) => { - try!(write!(self.writer, "[")); - if self.level >= 0 { - try!(write!(self.writer, "+ ")); - } - self.level += 1; - for (cnt, x) in v.iter().enumerate() { - try!(self.write_indent()); - if cnt > 0 { try!(write!(self.writer, ", ")); } - try!(self.emit_node(x)); - } - self.level -= 1; - try!(write!(self.writer, "]")); - Ok(()) - }, - Yaml::Hash(ref h) => { - try!(self.writer.write_str("{")); - self.level += 1; - for (cnt, (k, v)) in h.iter().enumerate() { - if cnt > 0 { - try!(write!(self.writer, ", ")); - } - match *k { - // complex key is not supported - Yaml::Array(_) | Yaml::Hash(_) => { - return Err(EmitError::BadHashmapKey); - }, - _ => { try!(self.emit_node(k)); } - } - try!(write!(self.writer, ": ")); - try!(self.emit_node(v)); - } - try!(self.writer.write_str("}")); - self.level -= 1; - Ok(()) - }, - _ => self.emit_node(node), - } - } - fn emit_node(&mut self, node: &Yaml) -> EmitResult { match *node { Yaml::Array(ref v) => self.emit_array(v), @@ -236,28 +194,37 @@ impl<'a> YamlEmitter<'a> { } else { self.level += 1; for (cnt, (k, v)) in h.iter().enumerate() { + let complex_key = match *k { + Yaml::Hash(_) | Yaml::Array(_) => true, + _ => false, + }; if cnt > 0 { try!(write!(self.writer, "\n")); try!(self.write_indent()); } - match *k { - Yaml::Array(_) | Yaml::Hash(_) => { - try!(self.emit_node_compact(k)); - } - _ => { - try!(self.emit_node(k)); - } + if complex_key { + try!(write!(self.writer, "? ")); + self.level += 1; + try!(self.emit_node(k)); + self.level -= 1; + try!(write!(self.writer, "\n")); + try!(self.write_indent()); + } else { + try!(self.emit_node(k)); } match *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 { @@ -267,10 +234,13 @@ impl<'a> YamlEmitter<'a> { 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; } } } } diff --git a/saphyr/tests/spec_test.rs b/saphyr/tests/spec_test.rs index b7316fc..3e5d043 100644 --- a/saphyr/tests/spec_test.rs +++ b/saphyr/tests/spec_test.rs @@ -73,3 +73,69 @@ include!("spec_test.rs.inc"); //#[test] //fn test_hc_alias() { //} + +#[test] +fn test_mapvec_legal() { + use yaml_rust::yaml::{Array, Hash, Yaml}; + use yaml_rust::{YamlLoader, YamlEmitter}; + + // Emitting a `map>, _>` should result in legal yaml that + // we can parse. + + let mut key = Array::new(); + key.push(Yaml::Integer(1)); + key.push(Yaml::Integer(2)); + key.push(Yaml::Integer(3)); + + let mut keyhash = Hash::new(); + keyhash.insert(Yaml::String("key".into()), Yaml::Array(key)); + + let mut val = Array::new(); + val.push(Yaml::Integer(4)); + val.push(Yaml::Integer(5)); + val.push(Yaml::Integer(6)); + + let mut hash = Hash::new(); + hash.insert(Yaml::Hash(keyhash), Yaml::Array(val)); + + let mut out_str = String::new(); + { + let mut emitter = YamlEmitter::new(&mut out_str); + emitter.dump(&Yaml::Hash(hash)).unwrap(); + } + + // At this point, we are tempted to naively render like this: + // + // ```yaml + // --- + // {key: + // - 1 + // - 2 + // - 3}: + // - 4 + // - 5 + // - 6 + // ``` + // + // However, this doesn't work, because the key sequence [1, 2, 3] is + // rendered in block mode, which is not legal (as far as I can tell) + // inside the flow mode of the key. We need to either fully render + // everything that's in a key in flow mode (which may make for some + // long lines), or use the explicit map identifier '?': + // + // ```yaml + // --- + // ? + // key: + // - 1 + // - 2 + // - 3 + // : + // - 4 + // - 5 + // - 6 + // ``` + + YamlLoader::load_from_str(&out_str).unwrap(); +} +