2018-08-25 18:38:44 -05:00
|
|
|
use std;
|
2019-02-19 15:06:06 -06:00
|
|
|
use std::error::Error;
|
2019-03-25 20:23:50 -04:00
|
|
|
use std::fmt::Write as FmtWrite;
|
2018-08-25 18:38:44 -05:00
|
|
|
use std::io::Write;
|
|
|
|
use std::rc::Rc;
|
2019-02-19 15:06:06 -06:00
|
|
|
use std::result::Result;
|
2018-08-25 18:38:44 -05:00
|
|
|
|
|
|
|
use serde_yaml;
|
|
|
|
|
2019-02-19 15:06:06 -06:00
|
|
|
use super::traits::{ConvertResult, Converter, ImportResult, Importer};
|
2018-12-06 12:23:52 -06:00
|
|
|
use crate::build::Val;
|
2018-08-25 18:38:44 -05:00
|
|
|
|
|
|
|
pub struct YamlConverter {}
|
|
|
|
|
|
|
|
impl YamlConverter {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
YamlConverter {}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn convert_list(&self, items: &Vec<Rc<Val>>) -> std::io::Result<serde_yaml::Value> {
|
|
|
|
let mut v = Vec::new();
|
|
|
|
for val in items.iter() {
|
2018-12-06 12:46:47 -06:00
|
|
|
v.push(self.convert_value(val)?);
|
2018-08-25 18:38:44 -05:00
|
|
|
}
|
|
|
|
Ok(serde_yaml::Value::Sequence(v))
|
|
|
|
}
|
|
|
|
|
2018-11-26 21:36:50 -06:00
|
|
|
fn convert_env(&self, items: &Vec<(String, String)>) -> std::io::Result<serde_yaml::Value> {
|
|
|
|
let mut mp = serde_yaml::Mapping::new();
|
|
|
|
for &(ref k, ref v) in items.iter() {
|
|
|
|
mp.insert(
|
|
|
|
serde_yaml::Value::String(k.clone()),
|
|
|
|
serde_yaml::Value::String(v.clone()),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
Ok(serde_yaml::Value::Mapping(mp))
|
|
|
|
}
|
|
|
|
|
2019-02-19 16:36:19 -06:00
|
|
|
fn convert_tuple(&self, items: &Vec<(String, Rc<Val>)>) -> std::io::Result<serde_yaml::Value> {
|
2018-08-25 18:38:44 -05:00
|
|
|
let mut mapping = serde_yaml::Mapping::new();
|
|
|
|
for &(ref k, ref v) in items.iter() {
|
2019-02-19 16:36:19 -06:00
|
|
|
mapping.insert(serde_yaml::Value::String(k.clone()), self.convert_value(v)?);
|
2018-08-25 18:38:44 -05:00
|
|
|
}
|
|
|
|
Ok(serde_yaml::Value::Mapping(mapping))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn convert_value(&self, v: &Val) -> std::io::Result<serde_yaml::Value> {
|
|
|
|
let yaml_val = match v {
|
|
|
|
&Val::Boolean(b) => serde_yaml::Value::Bool(b),
|
|
|
|
&Val::Empty => serde_yaml::Value::Null,
|
|
|
|
&Val::Float(f) => match serde_yaml::to_value(f) {
|
|
|
|
Ok(v) => v,
|
|
|
|
_ => panic!("Float is too large or not a Number {}", f),
|
|
|
|
},
|
|
|
|
&Val::Int(i) => match serde_yaml::to_value(i) {
|
|
|
|
Ok(v) => v,
|
|
|
|
_ => panic!("Int is too large or not a Number {}", i),
|
|
|
|
},
|
|
|
|
&Val::Str(ref s) => serde_yaml::Value::String(s.clone()),
|
2019-01-24 20:04:40 -06:00
|
|
|
&Val::Func(_) => {
|
|
|
|
eprintln!("Skipping func encoding as null...");
|
2018-08-25 18:38:44 -05:00
|
|
|
serde_yaml::Value::Null
|
|
|
|
}
|
2018-11-23 12:50:47 -06:00
|
|
|
&Val::Module(_) => {
|
|
|
|
eprintln!("Skipping module encoding as null...");
|
|
|
|
serde_yaml::Value::Null
|
|
|
|
}
|
2018-12-06 12:46:47 -06:00
|
|
|
&Val::Env(ref fs) => self.convert_env(fs)?,
|
|
|
|
&Val::List(ref l) => self.convert_list(l)?,
|
|
|
|
&Val::Tuple(ref t) => self.convert_tuple(t)?,
|
2018-08-25 18:38:44 -05:00
|
|
|
};
|
|
|
|
Ok(yaml_val)
|
|
|
|
}
|
|
|
|
|
2019-02-20 19:57:37 -06:00
|
|
|
fn convert_yaml_val(&self, v: &serde_yaml::Value) -> Result<Val, Box<dyn Error>> {
|
2019-02-19 15:06:06 -06:00
|
|
|
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 {
|
2019-02-20 19:57:37 -06:00
|
|
|
vs.push(Rc::new(self.convert_yaml_val(aval)?));
|
2019-02-19 15:06:06 -06:00
|
|
|
}
|
|
|
|
Val::List(vs)
|
|
|
|
}
|
|
|
|
serde_yaml::Value::Mapping(m) => {
|
|
|
|
let mut fs = Vec::with_capacity(m.len());
|
|
|
|
for (key, value) in m {
|
2019-02-19 15:27:16 -06:00
|
|
|
// This is a little gross but since yaml allows maps to be keyed
|
|
|
|
// by more than just a string it's necessary.
|
|
|
|
let key = match key {
|
|
|
|
serde_yaml::Value::Bool(b) => b.to_string(),
|
|
|
|
serde_yaml::Value::Null => "null".to_string(),
|
|
|
|
serde_yaml::Value::Number(n) => n.to_string(),
|
|
|
|
serde_yaml::Value::String(s) => s.clone(),
|
|
|
|
serde_yaml::Value::Sequence(_) | serde_yaml::Value::Mapping(_) => {
|
|
|
|
eprintln!("Unsupported key type in yaml import skipping");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
eprintln!("yaml key is: {}", key);
|
2019-02-20 19:57:37 -06:00
|
|
|
fs.push((key, Rc::new(self.convert_yaml_val(value)?)));
|
2019-02-19 15:06:06 -06:00
|
|
|
}
|
|
|
|
Val::Tuple(fs)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-19 14:50:55 -06:00
|
|
|
fn write(&self, v: &Val, w: &mut Write) -> ConvertResult {
|
2018-12-06 12:46:47 -06:00
|
|
|
let jsn_val = self.convert_value(v)?;
|
|
|
|
serde_yaml::to_writer(w, &jsn_val)?;
|
2018-08-25 18:38:44 -05:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Converter for YamlConverter {
|
2019-02-19 14:50:55 -06:00
|
|
|
fn convert(&self, v: Rc<Val>, mut w: &mut Write) -> ConvertResult {
|
2018-08-25 18:38:44 -05:00
|
|
|
self.write(&v, &mut w)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn file_ext(&self) -> String {
|
|
|
|
String::from("yaml")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn description(&self) -> String {
|
|
|
|
"Convert ucg Vals into valid yaml.".to_string()
|
|
|
|
}
|
2019-03-25 20:23:50 -04:00
|
|
|
|
|
|
|
#[allow(unused_must_use)]
|
|
|
|
fn help(&self) -> String {
|
|
|
|
let mut h = String::new();
|
|
|
|
writeln!(h, "YAML conversions expect any ucg value.");
|
|
|
|
writeln!(h, "");
|
|
|
|
writeln!(
|
|
|
|
h,
|
|
|
|
"They are transformed into toml using the following rules:"
|
|
|
|
);
|
|
|
|
writeln!(h, "- tuples become maps {{}}");
|
|
|
|
writeln!(h, "- lists become lists []");
|
|
|
|
writeln!(h, "- Int becomes an Int");
|
|
|
|
writeln!(h, "- Float becomes a Float");
|
|
|
|
writeln!(h, "- Strings become Strings.");
|
|
|
|
writeln!(h, "- Functions and Modules are ignored.");
|
|
|
|
h
|
|
|
|
}
|
2018-08-25 18:38:44 -05:00
|
|
|
}
|
2019-02-19 15:06:06 -06:00
|
|
|
|
|
|
|
impl Importer for YamlConverter {
|
|
|
|
fn import(&self, bytes: &[u8]) -> ImportResult {
|
|
|
|
let json_val = serde_yaml::from_slice(bytes)?;
|
2019-02-20 19:57:37 -06:00
|
|
|
Ok(Rc::new(self.convert_yaml_val(&json_val)?))
|
2019-02-19 15:06:06 -06:00
|
|
|
}
|
|
|
|
}
|