1use std;
12use std::error::Error;
13use std::io::Write;
14use std::rc::Rc;
15
16use serde_json;
17
18use crate::build::Val;
19use crate::convert::traits::{ConvertResult, Converter, ImportResult, Importer};
20
21pub struct JsonConverter {}
23
24impl JsonConverter {
25 pub fn new() -> Self {
26 JsonConverter {}
27 }
28
29 fn convert_list(&self, items: &Vec<Rc<Val>>) -> std::io::Result<serde_json::Value> {
30 let mut v = Vec::new();
31 for val in items.iter() {
32 v.push(self.convert_value(val)?);
33 }
34 Ok(serde_json::Value::Array(v))
35 }
36
37 fn convert_tuple(&self, items: &Vec<(String, Rc<Val>)>) -> std::io::Result<serde_json::Value> {
38 let mut mp = serde_json::Map::new();
39 for &(ref k, ref v) in items.iter() {
40 mp.entry(k.clone()).or_insert(self.convert_value(v)?);
41 }
42 Ok(serde_json::Value::Object(mp))
43 }
44
45 fn convert_env(&self, items: &Vec<(String, String)>) -> std::io::Result<serde_json::Value> {
46 let mut mp = serde_json::Map::new();
47 for &(ref k, ref v) in items.iter() {
48 mp.entry(k.clone())
49 .or_insert(serde_json::Value::String(v.clone()));
50 }
51 Ok(serde_json::Value::Object(mp))
52 }
53
54 fn convert_value(&self, v: &Val) -> std::io::Result<serde_json::Value> {
55 let jsn_val = match v {
56 &Val::Boolean(b) => serde_json::Value::Bool(b),
57 &Val::Empty => serde_json::Value::Null,
58 &Val::Float(f) => {
59 let n = match serde_json::Number::from_f64(f) {
60 Some(n) => n,
61 None => panic!("Float is too large or Not a Number {}", f),
63 };
64 serde_json::Value::Number(n)
65 }
66 &Val::Int(i) => {
67 let n = match serde_json::Number::from_f64(i as f64) {
68 Some(n) => n,
69 None => panic!("Float is too large or Not a Number {}", i),
71 };
72 serde_json::Value::Number(n)
73 }
74 &Val::Str(ref s) => serde_json::Value::String(s.clone()),
75 &Val::Env(ref fs) => self.convert_env(fs)?,
76 &Val::List(ref l) => self.convert_list(l)?,
77 &Val::Tuple(ref t) => self.convert_tuple(t)?,
78 };
79 Ok(jsn_val)
80 }
81
82 fn convert_json_val(&self, v: &serde_json::Value) -> std::result::Result<Val, Box<dyn Error>> {
83 Ok(match v {
84 serde_json::Value::String(s) => Val::Str(s.clone()),
85 serde_json::Value::Number(n) => {
86 if let Some(i) = n.as_i64() {
87 Val::Int(i)
88 } else {
89 Val::Float(n.as_f64().expect("Number was not an int or a float!!"))
90 }
91 }
92 serde_json::Value::Bool(b) => Val::Boolean(*b),
93 serde_json::Value::Null => Val::Empty,
94 serde_json::Value::Array(l) => {
95 let mut vs = Vec::with_capacity(l.len());
96 for aval in l {
97 vs.push(Rc::new(self.convert_json_val(aval)?));
98 }
99 Val::List(vs)
100 }
101 serde_json::Value::Object(m) => {
102 let mut fs = Vec::with_capacity(m.len());
103 for (key, value) in m {
104 fs.push((key.to_string(), Rc::new(self.convert_json_val(value)?)));
105 }
106 Val::Tuple(fs)
107 }
108 })
109 }
110
111 fn write(&self, v: &Val, w: &mut dyn Write) -> ConvertResult {
112 let jsn_val = self.convert_value(v)?;
113 serde_json::to_writer_pretty(w, &jsn_val)?;
114 Ok(())
115 }
116}
117
118impl Converter for JsonConverter {
119 fn convert(&self, v: Rc<Val>, mut w: &mut dyn Write) -> ConvertResult {
120 self.write(&v, &mut w)
121 }
122
123 fn file_ext(&self) -> String {
124 String::from("json")
125 }
126
127 fn description(&self) -> String {
128 "Convert ucg Vals into valid json.".to_string()
129 }
130
131 #[allow(unused_must_use)]
132 fn help(&self) -> String {
133 include_str!("json_help.txt").to_string()
134 }
135}
136
137impl Importer for JsonConverter {
138 fn import(&self, bytes: &[u8]) -> ImportResult {
139 let json_val = serde_json::from_slice(bytes)?;
140 Ok(Rc::new(self.convert_json_val(&json_val)?))
141 }
142}