Skip to content

Commit fc8cf0e

Browse files
author
David Orchard
committed
Use LinkedHashMap in place of HashMap
1 parent 62c8429 commit fc8cf0e

39 files changed

+144
-137
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ serde-hjson = { version = "0.9", default-features = false, optional = true }
3535
rust-ini = { version = "0.17", optional = true }
3636
ron = { version = "0.6", optional = true }
3737
json5_rs = { version = "0.3", optional = true, package = "json5" }
38+
linked-hash-map = { version = "0.5.4", features = ["serde_impl"] }
3839

3940
[dev-dependencies]
4041
serde_derive = "1.0.8"

examples/async_source/main.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use std::{collections::HashMap, error::Error};
1+
use linked_hash_map::LinkedHashMap;
2+
use std::error::Error;
23

34
use config::{builder::AsyncState, AsyncSource, ConfigBuilder, ConfigError, FileFormat};
45

@@ -56,7 +57,7 @@ struct HttpSource {
5657

5758
#[async_trait]
5859
impl AsyncSource for HttpSource {
59-
async fn collect(&self) -> Result<HashMap<String, config::Value>, ConfigError> {
60+
async fn collect(&self) -> Result<LinkedHashMap<String, config::Value>, ConfigError> {
6061
reqwest::get(&self.uri)
6162
.await
6263
.map_err(|e| ConfigError::Foreign(Box::new(e)))? // error conversion is possible from custom AsyncSource impls

examples/glob/src/main.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::path::Path;
2-
use std::collections::HashMap;
2+
use std::collections::LinkedHashMap;
33
use config::*;
44
use glob::glob;
55

@@ -14,9 +14,9 @@ fn main() {
1414
.merge(File::from(Path::new("conf/05-some.yml"))).unwrap()
1515
.merge(File::from(Path::new("conf/99-extra.json"))).unwrap();
1616

17-
// Print out our settings (as a HashMap)
17+
// Print out our settings (as a LinkedHashMap)
1818
println!("\n{:?} \n\n-----------",
19-
settings.try_into::<HashMap<String, String>>().unwrap());
19+
settings.try_into::<LinkedHashMap<String, String>>().unwrap());
2020

2121
// Option 2
2222
// --------
@@ -28,9 +28,9 @@ fn main() {
2828
File::from(Path::new("conf/99-extra.json"))])
2929
.unwrap();
3030

31-
// Print out our settings (as a HashMap)
31+
// Print out our settings (as a LinkedHashMap)
3232
println!("\n{:?} \n\n-----------",
33-
settings.try_into::<HashMap<String, String>>().unwrap());
33+
settings.try_into::<LinkedHashMap<String, String>>().unwrap());
3434

3535
// Option 3
3636
// --------
@@ -43,7 +43,7 @@ fn main() {
4343
.collect::<Vec<_>>())
4444
.unwrap();
4545

46-
// Print out our settings (as a HashMap)
46+
// Print out our settings (as a LinkedHashMap)
4747
println!("\n{:?} \n\n-----------",
48-
settings.try_into::<HashMap<String, String>>().unwrap());
48+
settings.try_into::<LinkedHashMap<String, String>>().unwrap());
4949
}

examples/simple/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::collections::LinkedHashMap;
22

33
fn main() {
44
let mut settings = config::Config::default();
@@ -9,7 +9,7 @@ fn main() {
99
// Eg.. `APP_DEBUG=1 ./target/app` would set the `debug` key
1010
.merge(config::Environment::with_prefix("APP")).unwrap();
1111

12-
// Print out our settings (as a HashMap)
12+
// Print out our settings (as a LinkedHashMap)
1313
println!("{:?}",
14-
settings.try_into::<HashMap<String, String>>().unwrap());
14+
settings.try_into::<LinkedHashMap<String, String>>().unwrap());
1515
}

examples/watch/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use config::*;
2-
use std::collections::HashMap;
2+
use std::collections::LinkedHashMap;
33
use std::sync::RwLock;
44
use notify::{RecommendedWatcher, DebouncedEvent, Watcher, RecursiveMode};
55
use std::sync::mpsc::channel;
@@ -20,7 +20,7 @@ fn show() {
2020
.read()
2121
.unwrap()
2222
.clone()
23-
.try_into::<HashMap<String, String>>()
23+
.try_into::<LinkedHashMap<String, String>>()
2424
.unwrap());
2525
}
2626

src/builder.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
use linked_hash_map::LinkedHashMap;
2+
use std::iter::IntoIterator;
13
use std::str::FromStr;
2-
use std::{collections::HashMap, iter::IntoIterator};
34

45
use crate::error::Result;
56
use crate::source::AsyncSource;
@@ -87,8 +88,8 @@ use crate::{config::Config, path::Expression, source::Source, value::Value};
8788
/// ```
8889
#[derive(Debug, Clone, Default)]
8990
pub struct ConfigBuilder<St: BuilderState> {
90-
defaults: HashMap<Expression, Value>,
91-
overrides: HashMap<Expression, Value>,
91+
defaults: LinkedHashMap<Expression, Value>,
92+
overrides: LinkedHashMap<Expression, Value>,
9293
state: St,
9394
}
9495

@@ -120,8 +121,8 @@ pub struct DefaultState {
120121
/// Refer to [`ConfigBuilder`] for similar API sample usage or to the examples folder of the crate, where such a source is implemented.
121122
#[derive(Debug, Clone, Default)]
122123
pub struct AsyncConfigBuilder {
123-
defaults: HashMap<Expression, Value>,
124-
overrides: HashMap<Expression, Value>,
124+
defaults: LinkedHashMap<Expression, Value>,
125+
overrides: LinkedHashMap<Expression, Value>,
125126
sources: Vec<SourceType>,
126127
}
127128

@@ -244,11 +245,11 @@ impl ConfigBuilder<DefaultState> {
244245
}
245246

246247
fn build_internal(
247-
defaults: HashMap<Expression, Value>,
248-
overrides: HashMap<Expression, Value>,
248+
defaults: LinkedHashMap<Expression, Value>,
249+
overrides: LinkedHashMap<Expression, Value>,
249250
sources: &[Box<dyn Source + Send + Sync>],
250251
) -> Result<Config> {
251-
let mut cache: Value = HashMap::<String, Value>::new().into();
252+
let mut cache: Value = LinkedHashMap::<String, Value>::new().into();
252253

253254
// Add defaults
254255
for (key, val) in defaults.into_iter() {
@@ -322,11 +323,11 @@ impl ConfigBuilder<AsyncState> {
322323
}
323324

324325
async fn build_internal(
325-
defaults: HashMap<Expression, Value>,
326-
overrides: HashMap<Expression, Value>,
326+
defaults: LinkedHashMap<Expression, Value>,
327+
overrides: LinkedHashMap<Expression, Value>,
327328
sources: &[SourceType],
328329
) -> Result<Config> {
329-
let mut cache: Value = HashMap::<String, Value>::new().into();
330+
let mut cache: Value = LinkedHashMap::<String, Value>::new().into();
330331

331332
// Add defaults
332333
for (key, val) in defaults.into_iter() {

src/config.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use linked_hash_map::LinkedHashMap;
22
use std::fmt::Debug;
33

44
use crate::builder::{ConfigBuilder, DefaultState};
@@ -16,8 +16,8 @@ use crate::value::{Table, Value};
1616
/// them according to the source's priority.
1717
#[derive(Clone, Debug)]
1818
pub struct Config {
19-
defaults: HashMap<path::Expression, Value>,
20-
overrides: HashMap<path::Expression, Value>,
19+
defaults: LinkedHashMap<path::Expression, Value>,
20+
overrides: LinkedHashMap<path::Expression, Value>,
2121
sources: Vec<Box<dyn Source + Send + Sync>>,
2222

2323
/// Root of the cached configuration.
@@ -83,7 +83,7 @@ impl Config {
8383
#[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
8484
pub fn refresh(&mut self) -> Result<&mut Config> {
8585
self.cache = {
86-
let mut cache: Value = HashMap::<String, Value>::new().into();
86+
let mut cache: Value = LinkedHashMap::<String, Value>::new().into();
8787

8888
// Add defaults
8989
for (key, val) in self.defaults.iter() {
@@ -181,7 +181,7 @@ impl Config {
181181
self.get(key).and_then(Value::into_bool)
182182
}
183183

184-
pub fn get_table(&self, key: &str) -> Result<HashMap<String, Value>> {
184+
pub fn get_table(&self, key: &str) -> Result<LinkedHashMap<String, Value>> {
185185
self.get(key).and_then(Value::into_table)
186186
}
187187

@@ -212,7 +212,7 @@ impl Source for Config {
212212
Box::new((*self).clone())
213213
}
214214

215-
fn collect(&self) -> Result<HashMap<String, Value>> {
215+
fn collect(&self) -> Result<LinkedHashMap<String, Value>> {
216216
self.cache.clone().into_table()
217217
}
218218
}

src/de.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use std::collections::{HashMap, VecDeque};
1+
use linked_hash_map::LinkedHashMap;
2+
use std::collections::VecDeque;
23
use std::iter::Enumerate;
34

45
use serde::de;
@@ -199,7 +200,7 @@ struct MapAccess {
199200
}
200201

201202
impl MapAccess {
202-
fn new(table: HashMap<String, Value>) -> Self {
203+
fn new(table: LinkedHashMap<String, Value>) -> Self {
203204
MapAccess {
204205
elements: table.into_iter().collect(),
205206
}

src/env.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use linked_hash_map::LinkedHashMap;
22
use std::env;
33

44
use crate::error::*;
@@ -79,8 +79,8 @@ impl Source for Environment {
7979
Box::new((*self).clone())
8080
}
8181

82-
fn collect(&self) -> Result<HashMap<String, Value>> {
83-
let mut m = HashMap::new();
82+
fn collect(&self) -> Result<LinkedHashMap<String, Value>> {
83+
let mut m = LinkedHashMap::new();
8484
let uri: String = "the environment".into();
8585

8686
let separator = self.separator.as_deref().unwrap_or("");

src/file/format/hjson.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
use std::collections::HashMap;
1+
use linked_hash_map::LinkedHashMap;
22
use std::error::Error;
33

44
use crate::value::{Value, ValueKind};
55

66
pub fn parse(
77
uri: Option<&String>,
88
text: &str,
9-
) -> Result<HashMap<String, Value>, Box<dyn Error + Send + Sync>> {
9+
) -> Result<LinkedHashMap<String, Value>, Box<dyn Error + Send + Sync>> {
1010
// Parse a JSON object value from the text
1111
// TODO: Have a proper error fire if the root of a file is ever not a Table
1212
let value = from_hjson_value(uri, &serde_hjson::from_str(text)?);
1313
match value.kind {
1414
ValueKind::Table(map) => Ok(map),
1515

16-
_ => Ok(HashMap::new()),
16+
_ => Ok(LinkedHashMap::new()),
1717
}
1818
}
1919

@@ -30,7 +30,7 @@ fn from_hjson_value(uri: Option<&String>, value: &serde_hjson::Value) -> Value {
3030
serde_hjson::Value::Bool(value) => Value::new(uri, ValueKind::Boolean(value)),
3131

3232
serde_hjson::Value::Object(ref table) => {
33-
let mut m = HashMap::new();
33+
let mut m = LinkedHashMap::new();
3434

3535
for (key, value) in table {
3636
m.insert(key.clone(), from_hjson_value(uri, value));

0 commit comments

Comments
 (0)