ucglib/convert/
json.rs

1//  You may obtain a copy of the License at
2//
3//      http://www.apache.org/licenses/LICENSE-2.0
4//
5//  Unless required by applicable law or agreed to in writing, software
6//  distributed under the License is distributed on an "AS IS" BASIS,
7//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8//  See the License for the specific language governing permissions and
9//  limitations under the License.
10//! Flags contains code for converting a UCG Val into the json output target.
11use 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
21/// JsonConverter implements the logic for converting a Val into the json output format.
22pub 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                    // In theory this should never happen. But on the off chance that it does...
62                    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                    // In theory this should never happen. But on the off chance that it does...
70                    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}