Skip to content

Commit c03fd36

Browse files
authored
Merge pull request #106 from tyranron/60-fix-defaults
Fix defaults serialization and 'invalid type: unit value' deserialization error (#60)
2 parents 2502fbc + a1eecd0 commit c03fd36

File tree

3 files changed

+93
-3
lines changed

3 files changed

+93
-3
lines changed

src/config.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use ser::ConfigSerializer;
1010
use source::Source;
1111

1212
use path;
13-
use value::{Value, ValueKind, ValueWithKey};
13+
use value::{Table, Value, ValueKind, ValueWithKey};
1414

1515
#[derive(Clone, Debug)]
1616
enum ConfigKind {
@@ -49,7 +49,12 @@ pub struct Config {
4949

5050
impl Config {
5151
pub fn new() -> Self {
52-
Config::default()
52+
Self {
53+
kind: ConfigKind::default(),
54+
// Config root should be instantiated as an empty table
55+
// to avoid deserialization errors.
56+
cache: Value::new(None, Table::new()),
57+
}
5358
}
5459

5560
/// Merge in a configuration property source.
@@ -129,6 +134,26 @@ impl Config {
129134
self.refresh()
130135
}
131136

137+
/// Set the configuration defaults by serializing them from given value.
138+
pub fn set_defaults<T>(&mut self, value: &T) -> Result<&mut Config>
139+
where
140+
T: Serialize,
141+
{
142+
match self.kind {
143+
ConfigKind::Mutable {
144+
ref mut defaults, ..
145+
} => {
146+
for (key, val) in Self::try_from(&value)?.collect()? {
147+
defaults.insert(key.parse()?, val);
148+
}
149+
}
150+
151+
ConfigKind::Frozen => return Err(ConfigError::Frozen),
152+
}
153+
154+
self.refresh()
155+
}
156+
132157
pub fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
133158
where
134159
T: Into<Value>,
@@ -192,13 +217,21 @@ impl Config {
192217
T::deserialize(self)
193218
}
194219

195-
/// Attempt to deserialize the entire configuration into the requested type.
220+
/// Attempt to serialize the entire configuration from the given type.
196221
pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
197222
let mut serializer = ConfigSerializer::default();
198223
from.serialize(&mut serializer)?;
199224
Ok(serializer.output)
200225
}
201226

227+
/// Attempt to serialize the entire configuration from the given type
228+
/// as default values.
229+
pub fn try_defaults_from<T: Serialize>(from: &T) -> Result<Self> {
230+
let mut c = Self::new();
231+
c.set_defaults(from)?;
232+
Ok(c)
233+
}
234+
202235
#[deprecated(since = "0.7.0", note = "please use 'try_into' instead")]
203236
pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
204237
self.try_into()

tests/defaults.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
extern crate config;
2+
3+
#[macro_use]
4+
extern crate serde_derive;
5+
6+
use config::*;
7+
8+
#[derive(Debug, Serialize, Deserialize)]
9+
pub struct Settings {
10+
pub db_host: String,
11+
}
12+
13+
impl Default for Settings {
14+
fn default() -> Self {
15+
Settings {
16+
db_host: String::from("default"),
17+
}
18+
}
19+
}
20+
21+
#[test]
22+
fn set_defaults() {
23+
let mut c = Config::new();
24+
c.set_defaults(&Settings::default())
25+
.expect("Setting defaults failed");
26+
let s: Settings = c.try_into().expect("Deserialization failed");
27+
28+
assert_eq!(s.db_host, "default");
29+
}
30+
31+
#[test]
32+
fn try_from_defaults() {
33+
let c = Config::try_from(&Settings::default()).expect("Serialization failed");
34+
let s: Settings = c.try_into().expect("Deserialization failed");
35+
assert_eq!(s.db_host, "default");
36+
}

tests/empty.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
extern crate config;
2+
3+
#[macro_use]
4+
extern crate serde_derive;
5+
6+
use config::*;
7+
8+
#[derive(Debug, Serialize, Deserialize)]
9+
struct Settings {
10+
#[serde(skip)]
11+
foo: isize,
12+
#[serde(skip)]
13+
bar: u8,
14+
}
15+
16+
#[test]
17+
fn empty_deserializes() {
18+
let s: Settings = Config::new().try_into().expect("Deserialization failed");
19+
assert_eq!(s.foo, 0);
20+
assert_eq!(s.bar, 0);
21+
}

0 commit comments

Comments
 (0)