From ba6014543dfb4040921bb4809c6b293cfdf33c84 Mon Sep 17 00:00:00 2001 From: "saber.wu" Date: Thu, 14 Jun 2018 17:09:43 +0800 Subject: support ini --- Cargo.toml | 5 +++- README.md | 4 +++- src/file/format/ini.rs | 32 +++++++++++++++++++++++++ src/file/format/mod.rs | 13 ++++++++++ src/lib.rs | 3 +++ tests/Settings-invalid.ini | 2 ++ tests/Settings.ini | 9 +++++++ tests/datetime.rs | 17 +++++++++++++ tests/file_ini.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++ tests/file_json.rs | 2 +- 10 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 src/file/format/ini.rs create mode 100644 tests/Settings-invalid.ini create mode 100644 tests/Settings.ini create mode 100644 tests/file_ini.rs diff --git a/Cargo.toml b/Cargo.toml index 8ee4d4c..8a33e4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,10 +14,12 @@ license = "MIT/Apache-2.0" travis-ci = { repository = "mehcode/config-rs" } [features] -default = ["toml", "json", "yaml", "hjson"] +default = ["toml", "json", "yaml", "hjson","ini"] json = ["serde_json"] yaml = ["yaml-rust"] hjson = ["serde-hjson"] +ini = [] + [dependencies] lazy_static = "1.0" @@ -28,6 +30,7 @@ toml = { version = "^0.4.1", optional = true } serde_json = { version = "^1.0.2", optional = true } yaml-rust = { version = "^0.4", optional = true } serde-hjson = { version = "^0.8.1", optional = true } +rust-ini = "0.12.1" [dev-dependencies] serde_derive = "^1.0.8" diff --git a/README.md b/README.md index ea2d4b0..b77daa9 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ - Set defaults - Set explicit values (to programmatically override) - - Read from [JSON], [TOML], [YAML] and [HJSON] files + - Read from [JSON], [TOML], [YAML], [HJSON], [INI] files - Read from environment - Loosely typed — Configuration values may be read in any supported type, as long as there exists a reasonable conversion - Access nested fields using a formatted path — Uses a subset of JSONPath; currently supports the child ( `redis.port` ) and subscript operators ( `databases[0].name` ) @@ -19,6 +19,7 @@ [TOML]: https://github.com/toml-lang/toml [YAML]: https://github.com/chyh1990/yaml-rust [HJSON]: https://github.com/hjson/hjson-rust +[INI]: https://github.com/zonyitoo/rust-ini ## Usage @@ -27,6 +28,7 @@ config = "0.8" ``` + - `ini` - Adds support for reading INI files - `json` - Adds support for reading JSON files - `hjson` - Adds support for reading HJSON files - `yaml` - Adds support for reading YAML files diff --git a/src/file/format/ini.rs b/src/file/format/ini.rs new file mode 100644 index 0000000..b7c0f71 --- /dev/null +++ b/src/file/format/ini.rs @@ -0,0 +1,32 @@ +use source::Source; +use std::collections::HashMap; +use std::error::Error; +use value::{Value, ValueKind}; +use ini::Ini; + +pub fn parse( + uri: Option<&String>, + text: &str, +) -> Result, Box> { + let mut map: HashMap = HashMap::new(); + let i = Ini::load_from_str(text)?; + for (sec, prop) in i.iter() { + match *sec { + Some(ref sec) => { + let mut sec_map: HashMap = HashMap::new(); + for (k, v) in prop.iter() { + sec_map.insert(k.to_lowercase().clone(), + Value::new(uri, ValueKind::String(v.clone()))); + } + map.insert(sec.to_lowercase().clone(), Value::new(uri, ValueKind::Table(sec_map))); + } + None => { + for (k, v) in prop.iter() { + map.insert(k.to_lowercase().clone(), + Value::new(uri, ValueKind::String(v.clone()))); + } + } + } + } + Ok(map) +} diff --git a/src/file/format/mod.rs b/src/file/format/mod.rs index 5dfdfde..65e2914 100644 --- a/src/file/format/mod.rs +++ b/src/file/format/mod.rs @@ -19,6 +19,9 @@ mod yaml; #[cfg(feature = "hjson")] mod hjson; +#[cfg(feature = "ini")] +mod ini; + #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub enum FileFormat { /// TOML (parsed with toml) @@ -36,6 +39,10 @@ pub enum FileFormat { /// HJSON (parsed with serde_hjson) #[cfg(feature = "hjson")] Hjson, + /// INI (parsed with serde_hjson) + #[cfg(feature = "ini")] + Ini, + } lazy_static! { @@ -56,6 +63,9 @@ lazy_static! { #[cfg(feature = "hjson")] formats.insert(FileFormat::Hjson, vec!["hjson"]); + #[cfg(feature = "ini")] + formats.insert(FileFormat::Ini, vec!["ini"]); + formats }; } @@ -90,6 +100,9 @@ impl FileFormat { #[cfg(feature = "hjson")] FileFormat::Hjson => hjson::parse(uri, text), + + #[cfg(feature = "ini")] + FileFormat::Ini => ini::parse(uri, text), } } } diff --git a/src/lib.rs b/src/lib.rs index 6178375..ad205d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,6 +43,9 @@ extern crate yaml_rust; #[cfg(feature = "hjson")] extern crate serde_hjson; +#[cfg(feature = "ini")] +extern crate ini; + mod error; mod value; mod de; diff --git a/tests/Settings-invalid.ini b/tests/Settings-invalid.ini new file mode 100644 index 0000000..f2b8d9b --- /dev/null +++ b/tests/Settings-invalid.ini @@ -0,0 +1,2 @@ +ok : true, +error diff --git a/tests/Settings.ini b/tests/Settings.ini new file mode 100644 index 0000000..16badd4 --- /dev/null +++ b/tests/Settings.ini @@ -0,0 +1,9 @@ +debug = true +production = false +[place] +name = Torre di Pisa +longitude = 43.7224985 +latitude = 10.3970522 +favorite = false +reviews = 3866 +rating = 4.5 diff --git a/tests/datetime.rs b/tests/datetime.rs index 89a34a1..26b395d 100644 --- a/tests/datetime.rs +++ b/tests/datetime.rs @@ -38,6 +38,13 @@ fn make() -> Config { FileFormat::Hjson, )) .unwrap() + .merge(File::from_str( + r#" + ini_datetime = 2017-05-10T02:14:53Z + "#, + FileFormat::Ini, + )) + .unwrap() .clone() } @@ -64,6 +71,11 @@ fn test_datetime_string() { let date: String = s.get("hjson_datetime").unwrap(); assert_eq!(&date, "2017-05-10T02:14:53Z"); + + // INI + let date: String = s.get("ini_datetime").unwrap(); + + assert_eq!(&date, "2017-05-10T02:14:53Z"); } #[test] @@ -89,4 +101,9 @@ fn test_datetime() { let date: DateTime = s.get("hjson_datetime").unwrap(); assert_eq!(date, Utc.ymd(2017, 5, 10).and_hms(2, 14, 53)); + + // INI + let date: DateTime = s.get("ini_datetime").unwrap(); + + assert_eq!(date, Utc.ymd(2017, 5, 10).and_hms(2, 14, 53)); } diff --git a/tests/file_ini.rs b/tests/file_ini.rs new file mode 100644 index 0000000..4c0030a --- /dev/null +++ b/tests/file_ini.rs @@ -0,0 +1,60 @@ +extern crate config; +extern crate serde; +extern crate float_cmp; + +#[macro_use] +extern crate serde_derive; + +use config::*; + +#[derive(Debug, Deserialize, PartialEq)] +struct Place { + name: String, + longitude: f64, + latitude: f64, + favorite: bool, + reviews: u64, + rating: Option, +} + +#[derive(Debug, Deserialize, PartialEq)] +struct Settings { + debug: f64, + place: Place, +} + +fn make() -> Config { + let mut c = Config::default(); + c.merge(File::new("tests/Settings", FileFormat::Ini)) + .unwrap(); + c +} + +#[test] +fn test_file() { + let c = make(); + let s: Settings = c.try_into().unwrap(); + assert_eq!(s, Settings { + debug: 1.0, + place: Place { + name: String::from("Torre di Pisa"), + longitude: 43.7224985, + latitude: 10.3970522, + favorite: false, + reviews: 3866, + rating: Some(4.5), + }, + }); +} + +#[test] +fn test_error_parse() { + let mut c = Config::default(); + let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Ini)); + + assert!(res.is_err()); + assert_eq!( + res.unwrap_err().to_string(), + r#"2:0 Expecting "[Some('='), Some(':')]" but found EOF. in tests/Settings-invalid.ini"# + ); +} diff --git a/tests/file_json.rs b/tests/file_json.rs index 1d35cae..8bffe23 100644 --- a/tests/file_json.rs +++ b/tests/file_json.rs @@ -72,4 +72,4 @@ fn test_error_parse() { res.unwrap_err().to_string(), "expected `:` at line 4 column 1 in tests/Settings-invalid.json".to_string() ); -} +} \ No newline at end of file -- cgit v1.2.3 From f259b6069ddf92becdb5edf300b8e2c2841b4812 Mon Sep 17 00:00:00 2001 From: "saber.wu" Date: Fri, 15 Jun 2018 13:15:43 +0800 Subject: fix doc test --- src/value.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/value.rs b/src/value.rs index a8ae94a..5d7562c 100644 --- a/src/value.rs +++ b/src/value.rs @@ -119,19 +119,17 @@ pub struct Value { /// A description of the original location of the value. /// /// A Value originating from a File might contain: - /// ``` + /// /// Settings.toml - /// ``` /// /// A Value originating from the environment would contain: - /// ``` + /// /// the envrionment - /// ``` /// /// A Value originating from a remote source might contain: - /// ``` + /// /// etcd+http://127.0.0.1:2379 - /// ``` + /// origin: Option, /// Underlying kind of the configuration value. -- cgit v1.2.3 From aa427d992894f4a098bd77b20d9f10801bc916e7 Mon Sep 17 00:00:00 2001 From: "san.dai" Date: Mon, 25 Jun 2018 16:38:06 +0800 Subject: option rust-ini --- Cargo.toml | 4 ++-- src/file/format/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8a33e4d..2551847 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ default = ["toml", "json", "yaml", "hjson","ini"] json = ["serde_json"] yaml = ["yaml-rust"] hjson = ["serde-hjson"] -ini = [] +ini = ["rust-ini"] [dependencies] @@ -30,7 +30,7 @@ toml = { version = "^0.4.1", optional = true } serde_json = { version = "^1.0.2", optional = true } yaml-rust = { version = "^0.4", optional = true } serde-hjson = { version = "^0.8.1", optional = true } -rust-ini = "0.12.1" +rust-ini = { version = "^0.12", optional = true } [dev-dependencies] serde_derive = "^1.0.8" diff --git a/src/file/format/mod.rs b/src/file/format/mod.rs index 65e2914..c01c386 100644 --- a/src/file/format/mod.rs +++ b/src/file/format/mod.rs @@ -39,7 +39,7 @@ pub enum FileFormat { /// HJSON (parsed with serde_hjson) #[cfg(feature = "hjson")] Hjson, - /// INI (parsed with serde_hjson) + /// INI (parsed with rust_ini) #[cfg(feature = "ini")] Ini, -- cgit v1.2.3