From 97d46e79b713ef7c75f9577cace1974f2a1ebd65 Mon Sep 17 00:00:00 2001 From: Gambhiro Date: Sat, 24 Dec 2016 13:22:01 +0000 Subject: [PATCH] convert json to toml before config parsing --- src/book/bookconfig.rs | 117 +++++++------- src/book/bookconfig_test.rs | 302 ++++++++++++++++++++++++++++++++++++ 2 files changed, 357 insertions(+), 62 deletions(-) diff --git a/src/book/bookconfig.rs b/src/book/bookconfig.rs index d0ba686e..50bcb76d 100644 --- a/src/book/bookconfig.rs +++ b/src/book/bookconfig.rs @@ -4,8 +4,8 @@ use std::process::exit; use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; - -//use serde::{Serialize, Deserialize}; +use std::collections::BTreeMap; +use std::str::FromStr; use serde_json; #[derive(Debug, Clone)] @@ -93,7 +93,29 @@ impl BookConfig { } }; - // TODO this is very similar to how the JSON is parsed. Combine somehow? + self.parse_from_btreemap(&config); + + self + } + + /// Parses the string to JSON and converts it to BTreeMap. + pub fn parse_from_json_string(&mut self, data: &String) -> &mut Self { + + let c: serde_json::Value = match serde_json::from_str(&data) { + Ok(x) => x, + Err(e) => { + error!("[*]: JSON parse errors in book.json: {:?}", e); + exit(2); + } + }; + + let config = json_object_to_btreemap(&c.as_object().unwrap()); + self.parse_from_btreemap(&config); + + self + } + + pub fn parse_from_btreemap(&mut self, config: &BTreeMap) -> &mut Self { // Title, author, description if let Some(a) = config.get("title") { @@ -138,65 +160,6 @@ impl BookConfig { self } - pub fn parse_from_json_string(&mut self, data: &String) -> &mut Self { - - let config: serde_json::Value = match serde_json::from_str(&data) { - Ok(x) => {x}, - Err(e) => { - error!("[*]: JSON parse errors in book.json: {:?}", e); - exit(2); - } - }; - - // Extract data - - let config = config.as_object().unwrap(); - - debug!("[*]: Extracting data from config"); - - // Title, author, description - if let Some(a) = config.get("title") { - self.title = a.to_string().replace("\"", "") - } - if let Some(a) = config.get("author") { - self.author = a.to_string().replace("\"", "") - } - if let Some(a) = config.get("description") { - self.description = a.to_string().replace("\"", "") - } - - // Destination folder - if let Some(a) = config.get("dest") { - let mut dest = PathBuf::from(&a.to_string().replace("\"", "")); - - // If path is relative make it absolute from the parent directory of src - if dest.is_relative() { - dest = self.get_root().join(&dest); - } - self.set_dest(&dest); - } - - // Source folder - if let Some(a) = config.get("src") { - let mut src = PathBuf::from(&a.to_string().replace("\"", "")); - if src.is_relative() { - src = self.get_root().join(&src); - } - self.set_src(&src); - } - - // Theme path folder - if let Some(a) = config.get("theme_path") { - let mut theme_path = PathBuf::from(&a.to_string().replace("\"", "")); - if theme_path.is_relative() { - theme_path = self.get_root().join(&theme_path); - } - self.set_theme_path(&theme_path); - } - - self - } - pub fn get_root(&self) -> &Path { &self.root } @@ -233,3 +196,33 @@ impl BookConfig { self } } + +pub fn json_object_to_btreemap(json: &serde_json::Map) -> BTreeMap { + let mut config: BTreeMap = BTreeMap::new(); + + for (key, value) in json.iter() { + config.insert( + String::from_str(key).unwrap(), + json_value_to_toml_value(value.to_owned()) + ); + } + + config +} + +pub fn json_value_to_toml_value(json: serde_json::Value) -> toml::Value { + match json { + serde_json::Value::Null => toml::Value::String("".to_string()), + serde_json::Value::Bool(x) => toml::Value::Boolean(x), + serde_json::Value::I64(x) => toml::Value::Integer(x), + serde_json::Value::U64(x) => toml::Value::Integer(x as i64), + serde_json::Value::F64(x) => toml::Value::Float(x), + serde_json::Value::String(x) => toml::Value::String(x), + serde_json::Value::Array(x) => { + toml::Value::Array(x.iter().map(|v| json_value_to_toml_value(v.to_owned())).collect()) + }, + serde_json::Value::Object(x) => { + toml::Value::Table(json_object_to_btreemap(&x)) + }, + } +} diff --git a/src/book/bookconfig_test.rs b/src/book/bookconfig_test.rs index fc18e9e7..9faf4522 100644 --- a/src/book/bookconfig_test.rs +++ b/src/book/bookconfig_test.rs @@ -1,6 +1,7 @@ #[cfg(test)] use std::path::Path; +use serde_json; use book::bookconfig::*; #[test] @@ -61,3 +62,304 @@ author = "Mathieu David" assert_eq!(format!("{:#?}", config), expected); } + +#[test] +fn it_parses_json_nested_array_to_toml() { + + // Example from: + // toml-0.2.1/tests/valid/arrays-nested.json + + let text = r#" +{ + "nest": { + "type": "array", + "value": [ + {"type": "array", "value": [ + {"type": "string", "value": "a"} + ]}, + {"type": "array", "value": [ + {"type": "string", "value": "b"} + ]} + ] + } +}"#; + + let c: serde_json::Value = serde_json::from_str(&text).unwrap(); + + let result = json_object_to_btreemap(&c.as_object().unwrap()); + + let expected = r#"{ + "nest": Table( + { + "type": String( + "array" + ), + "value": Array( + [ + Table( + { + "type": String( + "array" + ), + "value": Array( + [ + Table( + { + "type": String( + "string" + ), + "value": String( + "a" + ) + } + ) + ] + ) + } + ), + Table( + { + "type": String( + "array" + ), + "value": Array( + [ + Table( + { + "type": String( + "string" + ), + "value": String( + "b" + ) + } + ) + ] + ) + } + ) + ] + ) + } + ) +}"#; + + assert_eq!(format!("{:#?}", result), expected); +} + + +#[test] +fn it_parses_json_arrays_to_toml() { + + // Example from: + // toml-0.2.1/tests/valid/arrays.json + + let text = r#" +{ + "ints": { + "type": "array", + "value": [ + {"type": "integer", "value": "1"}, + {"type": "integer", "value": "2"}, + {"type": "integer", "value": "3"} + ] + }, + "floats": { + "type": "array", + "value": [ + {"type": "float", "value": "1.1"}, + {"type": "float", "value": "2.1"}, + {"type": "float", "value": "3.1"} + ] + }, + "strings": { + "type": "array", + "value": [ + {"type": "string", "value": "a"}, + {"type": "string", "value": "b"}, + {"type": "string", "value": "c"} + ] + }, + "dates": { + "type": "array", + "value": [ + {"type": "datetime", "value": "1987-07-05T17:45:00Z"}, + {"type": "datetime", "value": "1979-05-27T07:32:00Z"}, + {"type": "datetime", "value": "2006-06-01T11:00:00Z"} + ] + } +}"#; + + let c: serde_json::Value = serde_json::from_str(&text).unwrap(); + + let result = json_object_to_btreemap(&c.as_object().unwrap()); + + let expected = r#"{ + "dates": Table( + { + "type": String( + "array" + ), + "value": Array( + [ + Table( + { + "type": String( + "datetime" + ), + "value": String( + "1987-07-05T17:45:00Z" + ) + } + ), + Table( + { + "type": String( + "datetime" + ), + "value": String( + "1979-05-27T07:32:00Z" + ) + } + ), + Table( + { + "type": String( + "datetime" + ), + "value": String( + "2006-06-01T11:00:00Z" + ) + } + ) + ] + ) + } + ), + "floats": Table( + { + "type": String( + "array" + ), + "value": Array( + [ + Table( + { + "type": String( + "float" + ), + "value": String( + "1.1" + ) + } + ), + Table( + { + "type": String( + "float" + ), + "value": String( + "2.1" + ) + } + ), + Table( + { + "type": String( + "float" + ), + "value": String( + "3.1" + ) + } + ) + ] + ) + } + ), + "ints": Table( + { + "type": String( + "array" + ), + "value": Array( + [ + Table( + { + "type": String( + "integer" + ), + "value": String( + "1" + ) + } + ), + Table( + { + "type": String( + "integer" + ), + "value": String( + "2" + ) + } + ), + Table( + { + "type": String( + "integer" + ), + "value": String( + "3" + ) + } + ) + ] + ) + } + ), + "strings": Table( + { + "type": String( + "array" + ), + "value": Array( + [ + Table( + { + "type": String( + "string" + ), + "value": String( + "a" + ) + } + ), + Table( + { + "type": String( + "string" + ), + "value": String( + "b" + ) + } + ), + Table( + { + "type": String( + "string" + ), + "value": String( + "c" + ) + } + ) + ] + ) + } + ) +}"#; + + assert_eq!(format!("{:#?}", result), expected); +}