From e2b843035e30bb1517aadf9ad387637f90841642 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Tue, 19 Feb 2019 15:06:06 -0600 Subject: [PATCH] FEATURE: Yaml importer for include expressions. Yamls can be imported as UCG intermediate representation and used like native UCG types in your ucg files. --- src/convert/mod.rs | 1 + src/convert/yaml.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/convert/mod.rs b/src/convert/mod.rs index aa6663c..bf00ba7 100644 --- a/src/convert/mod.rs +++ b/src/convert/mod.rs @@ -93,6 +93,7 @@ impl ImporterRegistry { Box::new(b64::Base64Importer { url_safe: true }), ); registry.register("json", Box::new(json::JsonConverter {})); + registry.register("yaml", Box::new(yaml::YamlConverter {})); registry } diff --git a/src/convert/yaml.rs b/src/convert/yaml.rs index 4cd0f51..54c74a8 100644 --- a/src/convert/yaml.rs +++ b/src/convert/yaml.rs @@ -1,10 +1,12 @@ use std; +use std::error::Error; use std::io::Write; use std::rc::Rc; +use std::result::Result; use serde_yaml; -use super::traits::{ConvertResult, Converter}; +use super::traits::{ConvertResult, Converter, ImportResult, Importer}; use crate::ast; use crate::build::Val; @@ -76,6 +78,43 @@ impl YamlConverter { Ok(yaml_val) } + fn convert_json_val(&self, v: &serde_yaml::Value) -> Result> { + Ok(match v { + serde_yaml::Value::String(s) => Val::Str(s.clone()), + serde_yaml::Value::Number(n) => { + if let Some(i) = n.as_i64() { + Val::Int(i) + } else { + Val::Float(n.as_f64().expect("Number was not an int or a float!!")) + } + } + serde_yaml::Value::Bool(b) => Val::Boolean(*b), + serde_yaml::Value::Null => Val::Empty, + serde_yaml::Value::Sequence(l) => { + let mut vs = Vec::with_capacity(l.len()); + for aval in l { + vs.push(Rc::new(self.convert_json_val(aval)?)); + } + Val::List(vs) + } + serde_yaml::Value::Mapping(m) => { + let mut fs = Vec::with_capacity(m.len()); + for (key, value) in m { + fs.push(( + ast::PositionedItem::new( + // This is a little gross but since yaml allows maps to be keyed + // by more than just a string it's necessary. + serde_yaml::to_string(key)?, + ast::Position::new(0, 0, 0), + ), + Rc::new(self.convert_json_val(value)?), + )); + } + Val::Tuple(fs) + } + }) + } + fn write(&self, v: &Val, w: &mut Write) -> ConvertResult { let jsn_val = self.convert_value(v)?; serde_yaml::to_writer(w, &jsn_val)?; @@ -96,3 +135,10 @@ impl Converter for YamlConverter { "Convert ucg Vals into valid yaml.".to_string() } } + +impl Importer for YamlConverter { + fn import(&self, bytes: &[u8]) -> ImportResult { + let json_val = serde_yaml::from_slice(bytes)?; + Ok(Rc::new(self.convert_json_val(&json_val)?)) + } +}