diff --git a/src/file/format/json.rs b/src/file/format/json.rs index 1720cb60..bd506f0d 100644 --- a/src/file/format/json.rs +++ b/src/file/format/json.rs @@ -1,5 +1,6 @@ use std::error::Error; +use crate::format; use crate::map::Map; use crate::value::{Value, ValueKind}; @@ -8,13 +9,8 @@ pub fn parse( text: &str, ) -> Result, Box> { // Parse a JSON object value from the text - // TODO: Have a proper error fire if the root of a file is ever not a Table let value = from_json_value(uri, &serde_json::from_str(text)?); - match value.kind { - ValueKind::Table(map) => Ok(map), - - _ => Ok(Map::new()), - } + format::extract_root_table(uri, value) } fn from_json_value(uri: Option<&String>, value: &serde_json::Value) -> Value { diff --git a/src/file/format/json5.rs b/src/file/format/json5.rs index 92aaa8f9..99003bd0 100644 --- a/src/file/format/json5.rs +++ b/src/file/format/json5.rs @@ -1,6 +1,6 @@ use std::error::Error; -use crate::error::{ConfigError, Unexpected}; +use crate::format; use crate::map::Map; use crate::value::{Value, ValueKind}; @@ -20,20 +20,8 @@ pub fn parse( uri: Option<&String>, text: &str, ) -> Result, Box> { - match json5_rs::from_str::(text)? { - Val::String(ref value) => Err(Unexpected::Str(value.clone())), - Val::Integer(value) => Err(Unexpected::I64(value)), - Val::Float(value) => Err(Unexpected::Float(value)), - Val::Boolean(value) => Err(Unexpected::Bool(value)), - Val::Array(_) => Err(Unexpected::Seq), - Val::Null => Err(Unexpected::Unit), - Val::Object(o) => match from_json5_value(uri, Val::Object(o)).kind { - ValueKind::Table(map) => Ok(map), - _ => Ok(Map::new()), - }, - } - .map_err(|err| ConfigError::invalid_root(uri, err)) - .map_err(|err| Box::new(err) as Box) + let value = from_json5_value(uri, json5_rs::from_str::(text)?); + format::extract_root_table(uri, value) } fn from_json5_value(uri: Option<&String>, value: Val) -> Value { diff --git a/src/file/format/ron.rs b/src/file/format/ron.rs index fb2b0636..9ac81a9d 100644 --- a/src/file/format/ron.rs +++ b/src/file/format/ron.rs @@ -1,5 +1,6 @@ use std::error::Error; +use crate::format; use crate::map::Map; use crate::value::{Value, ValueKind}; @@ -8,11 +9,7 @@ pub fn parse( text: &str, ) -> Result, Box> { let value = from_ron_value(uri, ron::from_str(text)?)?; - match value.kind { - ValueKind::Table(map) => Ok(map), - - _ => Ok(Map::new()), - } + format::extract_root_table(uri, value) } fn from_ron_value( diff --git a/src/file/format/toml.rs b/src/file/format/toml.rs index af21fc78..19b78044 100644 --- a/src/file/format/toml.rs +++ b/src/file/format/toml.rs @@ -1,20 +1,16 @@ 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 TOML value from the provided text - // TODO: Have a proper error fire if the root of a file is ever not a Table let value = from_toml_value(uri, &toml::from_str(text)?); - match value.kind { - ValueKind::Table(map) => Ok(map), - - _ => Ok(Map::new()), - } + format::extract_root_table(uri, value) } fn from_toml_value(uri: Option<&String>, value: &toml::Value) -> Value { diff --git a/src/file/format/yaml.rs b/src/file/format/yaml.rs index c9c8a224..b35ba4d9 100644 --- a/src/file/format/yaml.rs +++ b/src/file/format/yaml.rs @@ -4,6 +4,7 @@ use std::mem; use yaml_rust as yaml; +use crate::format; use crate::map::Map; use crate::value::{Value, ValueKind}; @@ -21,13 +22,8 @@ pub fn parse( } }; - // TODO: Have a proper error fire if the root of a file is ever not a Table let value = from_yaml_value(uri, &root)?; - match value.kind { - ValueKind::Table(map) => Ok(map), - - _ => Ok(Map::new()), - } + format::extract_root_table(uri, value) } fn from_yaml_value( diff --git a/src/format.rs b/src/format.rs index ab9e4fa2..3d1ca335 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,6 +1,8 @@ use std::error::Error; -use crate::{map::Map, value::Value}; +use crate::error::{ConfigError, Unexpected}; +use crate::map::Map; +use crate::value::{Value, ValueKind}; /// Describes a format of configuration source data /// @@ -21,3 +23,24 @@ pub trait Format { text: &str, ) -> Result, Box>; } + +// Have a proper error fire if the root of a file is ever not a Table +pub fn extract_root_table( + uri: Option<&String>, + value: Value, +) -> Result, Box> { + match value.kind { + ValueKind::Table(map) => Ok(map), + ValueKind::Nil => Err(Unexpected::Unit), + ValueKind::Array(_value) => Err(Unexpected::Seq), + ValueKind::Boolean(value) => Err(Unexpected::Bool(value)), + ValueKind::I64(value) => Err(Unexpected::I64(value)), + ValueKind::I128(value) => Err(Unexpected::I128(value)), + ValueKind::U64(value) => Err(Unexpected::U64(value)), + ValueKind::U128(value) => Err(Unexpected::U128(value)), + ValueKind::Float(value) => Err(Unexpected::Float(value)), + ValueKind::String(value) => Err(Unexpected::Str(value)), + } + .map_err(|err| ConfigError::invalid_root(uri, err)) + .map_err(|err| Box::new(err) as Box) +}