FEATURE: Add json as an include format.

Include a json file and it will be transformed into the UCG
intermediate format and usable in your ucg file.
This commit is contained in:
Jeremy Wall 2019-02-19 14:45:46 -06:00
parent bcf1850f73
commit fdbbf0fb01
3 changed files with 45 additions and 1 deletions

View File

@ -9,6 +9,7 @@
// limitations under the License. // limitations under the License.
//! Flags contains code for converting a UCG Val into the json output target. //! Flags contains code for converting a UCG Val into the json output target.
use std; use std;
use std::error::Error;
use std::io::Write; use std::io::Write;
use std::rc::Rc; use std::rc::Rc;
@ -16,7 +17,7 @@ use serde_json;
use crate::ast; use crate::ast;
use crate::build::Val; use crate::build::Val;
use crate::convert::traits::{Converter, Result}; use crate::convert::traits::{Converter, ImportResult, Importer, Result};
/// JsonConverter implements the logic for converting a Val into the json output format. /// JsonConverter implements the logic for converting a Val into the json output format.
pub struct JsonConverter {} pub struct JsonConverter {}
@ -90,6 +91,38 @@ impl JsonConverter {
Ok(jsn_val) Ok(jsn_val)
} }
fn convert_json_val(&self, v: &serde_json::Value) -> std::result::Result<Val, Box<dyn Error>> {
Ok(match v {
serde_json::Value::String(s) => Val::Str(s.clone()),
serde_json::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_json::Value::Bool(b) => Val::Boolean(*b),
serde_json::Value::Null => Val::Empty,
serde_json::Value::Array(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_json::Value::Object(m) => {
let mut fs = Vec::with_capacity(m.len());
for (key, value) in m {
fs.push((
ast::PositionedItem::new(key.to_string(), ast::Position::new(0, 0, 0)),
Rc::new(self.convert_json_val(value)?),
));
}
Val::Tuple(fs)
}
})
}
fn write(&self, v: &Val, w: &mut Write) -> Result { fn write(&self, v: &Val, w: &mut Write) -> Result {
let jsn_val = self.convert_value(v)?; let jsn_val = self.convert_value(v)?;
serde_json::to_writer_pretty(w, &jsn_val)?; serde_json::to_writer_pretty(w, &jsn_val)?;
@ -110,3 +143,10 @@ impl Converter for JsonConverter {
"Convert ucg Vals into valid json.".to_string() "Convert ucg Vals into valid json.".to_string()
} }
} }
impl Importer for JsonConverter {
fn import(&self, bytes: &[u8]) -> ImportResult {
let json_val = serde_json::from_slice(bytes)?;
Ok(Rc::new(self.convert_json_val(&json_val)?))
}
}

View File

@ -92,6 +92,7 @@ impl ImporterRegistry {
"b64urlsafe", "b64urlsafe",
Box::new(b64::Base64Importer { url_safe: true }), Box::new(b64::Base64Importer { url_safe: true }),
); );
registry.register("json", Box::new(json::JsonConverter {}));
registry registry
} }

View File

@ -20,8 +20,11 @@ use std::result;
use crate::build::Val; use crate::build::Val;
// TODO Rename to ConvertResult
pub type Result = result::Result<(), Box<dyn Error>>; pub type Result = result::Result<(), Box<dyn Error>>;
pub type ImportResult = result::Result<Rc<Val>, Box<dyn Error>>;
/// The trait that Converters from Val to different output formats for the /// The trait that Converters from Val to different output formats for the
/// final conversion stage of the ucg compiler. /// final conversion stage of the ucg compiler.
pub trait Converter { pub trait Converter {