diff --git a/src/file/format/json.rs b/src/file/format/json.rs index bd506f0d..025219a0 100644 --- a/src/file/format/json.rs +++ b/src/file/format/json.rs @@ -2,53 +2,13 @@ use std::error::Error; use crate::format; use crate::map::Map; -use crate::value::{Value, ValueKind}; +use crate::value::Value; pub fn parse( uri: Option<&String>, text: &str, ) -> Result, Box> { - // Parse a JSON object value from the text - let value = from_json_value(uri, &serde_json::from_str(text)?); + // Parse a JSON input from the provided text + let value = format::from_parsed_value(uri, serde_json::from_str(text)?); format::extract_root_table(uri, value) } - -fn from_json_value(uri: Option<&String>, value: &serde_json::Value) -> Value { - match *value { - serde_json::Value::String(ref value) => Value::new(uri, ValueKind::String(value.clone())), - - serde_json::Value::Number(ref value) => { - if let Some(value) = value.as_i64() { - Value::new(uri, ValueKind::I64(value)) - } else if let Some(value) = value.as_f64() { - Value::new(uri, ValueKind::Float(value)) - } else { - unreachable!(); - } - } - - serde_json::Value::Bool(value) => Value::new(uri, ValueKind::Boolean(value)), - - serde_json::Value::Object(ref table) => { - let mut m = Map::new(); - - for (key, value) in table { - m.insert(key.clone(), from_json_value(uri, value)); - } - - Value::new(uri, ValueKind::Table(m)) - } - - serde_json::Value::Array(ref array) => { - let mut l = Vec::new(); - - for value in array { - l.push(from_json_value(uri, value)); - } - - Value::new(uri, ValueKind::Array(l)) - } - - serde_json::Value::Null => Value::new(uri, ValueKind::Nil), - } -} diff --git a/src/file/format/json5.rs b/src/file/format/json5.rs index 99003bd0..242a4725 100644 --- a/src/file/format/json5.rs +++ b/src/file/format/json5.rs @@ -2,53 +2,13 @@ use std::error::Error; use crate::format; use crate::map::Map; -use crate::value::{Value, ValueKind}; - -#[derive(serde::Deserialize, Debug)] -#[serde(untagged)] -pub enum Val { - Null, - Boolean(bool), - Integer(i64), - Float(f64), - String(String), - Array(Vec), - Object(Map), -} +use crate::value::Value; pub fn parse( uri: Option<&String>, text: &str, ) -> Result, Box> { - let value = from_json5_value(uri, json5_rs::from_str::(text)?); + // Parse a JSON5 input from the provided text + let value = format::from_parsed_value(uri, json5_rs::from_str(text)?); format::extract_root_table(uri, value) } - -fn from_json5_value(uri: Option<&String>, value: Val) -> Value { - let vk = match value { - Val::Null => ValueKind::Nil, - Val::String(v) => ValueKind::String(v), - Val::Integer(v) => ValueKind::I64(v), - Val::Float(v) => ValueKind::Float(v), - Val::Boolean(v) => ValueKind::Boolean(v), - Val::Object(table) => { - let m = table - .into_iter() - .map(|(k, v)| (k, from_json5_value(uri, v))) - .collect(); - - ValueKind::Table(m) - } - - Val::Array(array) => { - let l = array - .into_iter() - .map(|v| from_json5_value(uri, v)) - .collect(); - - ValueKind::Array(l) - } - }; - - Value::new(uri, vk) -} diff --git a/src/file/format/toml.rs b/src/file/format/toml.rs index 19b78044..55931698 100644 --- a/src/file/format/toml.rs +++ b/src/file/format/toml.rs @@ -8,38 +8,7 @@ pub fn parse( uri: Option<&String>, text: &str, ) -> Result, Box> { - // Parse a TOML value from the provided text - let value = from_toml_value(uri, &toml::from_str(text)?); + // Parse a TOML input from the provided text + let value = format::from_parsed_value(uri, toml::from_str(text)?); format::extract_root_table(uri, value) } - -fn from_toml_value(uri: Option<&String>, value: &toml::Value) -> Value { - match *value { - toml::Value::String(ref value) => Value::new(uri, value.to_string()), - toml::Value::Float(value) => Value::new(uri, value), - toml::Value::Integer(value) => Value::new(uri, value), - toml::Value::Boolean(value) => Value::new(uri, value), - - toml::Value::Table(ref table) => { - let mut m = Map::new(); - - for (key, value) in table { - m.insert(key.clone(), from_toml_value(uri, value)); - } - - Value::new(uri, m) - } - - toml::Value::Array(ref array) => { - let mut l = Vec::new(); - - for value in array { - l.push(from_toml_value(uri, value)); - } - - Value::new(uri, l) - } - - toml::Value::Datetime(ref datetime) => Value::new(uri, datetime.to_string()), - } -} diff --git a/src/format.rs b/src/format.rs index 3d1ca335..1556645b 100644 --- a/src/format.rs +++ b/src/format.rs @@ -44,3 +44,53 @@ pub fn extract_root_table( .map_err(|err| ConfigError::invalid_root(uri, err)) .map_err(|err| Box::new(err) as Box) } + +// Equivalent to ValueKind, except Table + Array store the same enum +// Useful for serde to serialize values into, then convert to Value +#[derive(serde::Deserialize, Debug)] +#[serde(untagged)] +pub enum ParsedValue { + Nil, + Boolean(bool), + I64(i64), + I128(i128), + U64(u64), + U128(u128), + Float(f64), + String(String), + Table(Map), + Array(Vec), +} + +// Value wrap ValueKind values, with optional uri (origin) +pub fn from_parsed_value(uri: Option<&String>, value: ParsedValue) -> Value { + let vk = match value { + ParsedValue::Nil => ValueKind::Nil, + ParsedValue::String(v) => ValueKind::String(v), + ParsedValue::I64(v) => ValueKind::I64(v), + ParsedValue::I128(v) => ValueKind::I128(v), + ParsedValue::U64(v) => ValueKind::U64(v), + ParsedValue::U128(v) => ValueKind::U128(v), + ParsedValue::Float(v) => ValueKind::Float(v), + ParsedValue::Boolean(v) => ValueKind::Boolean(v), + ParsedValue::Table(table) => { + let m = table + .into_iter() + .map(|(k, v)| (k, from_parsed_value(uri, v))) + .collect(); + + ValueKind::Table(m) + } + + ParsedValue::Array(array) => { + let l = array + .into_iter() + .map(|v| from_parsed_value(uri, v)) + .collect(); + + ValueKind::Array(l) + } + }; + + Value::new(uri, vk) +}