diff options
author | up9cloud <8325632+up9cloud@users.noreply.github.com> | 2020-07-06 13:07:05 -0700 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2021-05-15 14:35:58 +0200 |
commit | 70c503af8b3cb3d73bbbea673bb49460df318e5e (patch) | |
tree | 3550f1015af6186e5f6c1cade83345ee48609e22 /src/file | |
parent | 266f504d9f23e192c03ef486f58a678847249b60 (diff) |
Support format json5
Diffstat (limited to 'src/file')
-rw-r--r-- | src/file/format/json5.rs | 78 | ||||
-rw-r--r-- | src/file/format/mod.rs | 14 |
2 files changed, 92 insertions, 0 deletions
diff --git a/src/file/format/json5.rs b/src/file/format/json5.rs new file mode 100644 index 0000000..320e574 --- /dev/null +++ b/src/file/format/json5.rs @@ -0,0 +1,78 @@ +use serde_derive::Deserialize; + +use std::collections::HashMap; +use std::error::Error; + +use crate::error::{ConfigError, Unexpected}; +use crate::value::{Value, ValueKind}; + +#[derive(Deserialize, Debug)] +#[serde(untagged)] +pub enum Val { + Null, + Boolean(bool), + Integer(i64), + Float(f64), + String(String), + Array(Vec<Val>), + Object(HashMap<String, Val>), +} + +pub fn parse( + uri: Option<&String>, + text: &str, +) -> Result<HashMap<String, Value>, Box<dyn Error + Send + Sync>> { + let root = json5_rs::from_str::<Val>(&text)?; + if let Some(err) = match root { + Val::String(ref value) => Some(Unexpected::Str(value.clone())), + Val::Integer(value) => Some(Unexpected::Integer(value)), + Val::Float(value) => Some(Unexpected::Float(value)), + Val::Boolean(value) => Some(Unexpected::Bool(value)), + Val::Object(_) => None, + Val::Array(_) => Some(Unexpected::Seq), + Val::Null => Some(Unexpected::Unit), + } { + return Err(ConfigError::invalid_root(uri, err)); + } + + let value = from_json5_value(uri, root); + match value.kind { + ValueKind::Table(map) => Ok(map), + + _ => Ok(HashMap::new()), + } +} + +fn from_json5_value(uri: Option<&String>, value: Val) -> Value { + match value { + Val::String(v) => Value::new(uri, ValueKind::String(v)), + + Val::Integer(v) => Value::new(uri, ValueKind::Integer(v)), + + Val::Float(v) => Value::new(uri, ValueKind::Float(v)), + + Val::Boolean(v) => Value::new(uri, ValueKind::Boolean(v)), + + Val::Object(table) => { + let mut m = HashMap::new(); + + for (key, value) in table { + m.insert(key, from_json5_value(uri, value)); + } + + Value::new(uri, ValueKind::Table(m)) + } + + Val::Array(array) => { + let mut l = Vec::new(); + + for value in array { + l.push(from_json5_value(uri, value)); + } + + Value::new(uri, ValueKind::Array(l)) + } + + Val::Null => Value::new(uri, ValueKind::Nil), + } +} diff --git a/src/file/format/mod.rs b/src/file/format/mod.rs index bbd62a2..53bacf6 100644 --- a/src/file/format/mod.rs +++ b/src/file/format/mod.rs @@ -25,6 +25,9 @@ mod ini; #[cfg(feature = "ron")] mod ron; +#[cfg(feature = "json5")] +mod json5; + #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub enum FileFormat { /// TOML (parsed with toml) @@ -42,6 +45,7 @@ pub enum FileFormat { /// HJSON (parsed with serde_hjson) #[cfg(feature = "hjson")] Hjson, + /// INI (parsed with rust_ini) #[cfg(feature = "ini")] Ini, @@ -49,6 +53,10 @@ pub enum FileFormat { /// RON (parsed with ron) #[cfg(feature = "ron")] Ron, + + /// JSON5 (parsed with json5) + #[cfg(feature = "json5")] + Json5, } lazy_static! { @@ -75,6 +83,9 @@ lazy_static! { #[cfg(feature = "ron")] formats.insert(FileFormat::Ron, vec!["ron"]); + #[cfg(feature = "json5")] + formats.insert(FileFormat::Json5, vec!["json5"]); + formats }; } @@ -115,6 +126,9 @@ impl FileFormat { #[cfg(feature = "ron")] FileFormat::Ron => ron::parse(uri, text), + + #[cfg(feature = "json5")] + FileFormat::Json5 => json5::parse(uri, text), } } } |