summaryrefslogtreecommitdiffstats
path: root/src/file
diff options
context:
space:
mode:
authorup9cloud <8325632+up9cloud@users.noreply.github.com>2020-07-06 13:07:05 -0700
committerMatthias Beyer <mail@beyermatthias.de>2021-05-15 14:35:58 +0200
commit70c503af8b3cb3d73bbbea673bb49460df318e5e (patch)
tree3550f1015af6186e5f6c1cade83345ee48609e22 /src/file
parent266f504d9f23e192c03ef486f58a678847249b60 (diff)
Support format json5
Diffstat (limited to 'src/file')
-rw-r--r--src/file/format/json5.rs78
-rw-r--r--src/file/format/mod.rs14
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),
}
}
}