@@ -196,41 +196,97 @@ macro_rules! create_config {
196
196
$( pub $i: $ty) ,+
197
197
}
198
198
199
- // Just like the Config struct but with each property wrapped
200
- // as Option<T>. This is used to parse a rustfmt.toml that doesn't
201
- // specity all properties of `Config`.
202
- // We first parse into `ParsedConfig`, then create a default `Config`
203
- // and overwrite the properties with corresponding values from `ParsedConfig`
199
+ /// Equivalent to `Config` except that each field is wrapped in an `Option`.
200
+ ///
201
+ /// This can be decoded into from TOML, and then later merged into a `Config` or another
202
+ /// `PartialConfig`.
203
+ ///
204
+ /// # Examples
205
+ ///
206
+ /// Decode a TOML value into a `PartialConfig`:
207
+ ///
208
+ /// ```ignore
209
+ /// extern crate toml;
210
+ /// let toml_str = r#"
211
+ /// ideal_width = 72
212
+ /// "#;
213
+ ///
214
+ /// let partial: PartialConfig = toml::decode_str(toml_str);
215
+ /// ```
216
+ ///
217
+ /// Later, merge the `PartialConfig` into the default `Config`:
218
+ ///
219
+ /// ```ignore
220
+ /// # extern crate toml;
221
+ /// # use config::{Config, PartialConfig};
222
+ ///
223
+ /// # let toml_value = "abc = 3".parse().expect("Could not parse TOML");
224
+ /// # let partial: PartialConfig = toml::decode(toml_value);
225
+ /// let config = Config::Default().merge(partial);
226
+ /// assert_eq!(72, config.ideal_width);
227
+ /// ```
204
228
#[ derive( RustcDecodable , Clone ) ]
205
- pub struct ParsedConfig {
229
+ pub struct PartialConfig {
206
230
$( pub $i: Option <$ty>) ,+
207
231
}
208
232
233
+ impl PartialConfig {
234
+
235
+ /// Create a `PartialConfig` with all fields set to `None`.
236
+ pub fn new( ) -> PartialConfig {
237
+ PartialConfig {
238
+ $(
239
+ $i: None ,
240
+ ) +
241
+ }
242
+
243
+ }
244
+
245
+ /// Merge `other` into `self, overwriting fields in `self` with any non-`None` fields
246
+ /// in `other`.
247
+ pub fn merge( & mut self , other: & PartialConfig ) -> & mut PartialConfig {
248
+ $(
249
+ if other. $i. is_some( ) {
250
+ self . $i = other. $i. clone( ) ;
251
+ }
252
+ ) +
253
+ self
254
+ }
255
+ }
256
+
257
+ impl Default for PartialConfig {
258
+ fn default ( ) -> PartialConfig {
259
+ PartialConfig :: new( )
260
+ }
261
+ }
262
+
263
+ /// Applies settings in `partial` on top of the default `Config`.
264
+ impl From <PartialConfig > for Config {
265
+ fn from( partial: PartialConfig ) -> Config {
266
+ Config :: default ( ) . merge( & partial)
267
+ }
268
+ }
269
+
270
+ /// Applies settings in `partial` on top of the default `Config`.
271
+ impl <' a> From <& ' a PartialConfig > for Config {
272
+ fn from( partial: & ' a PartialConfig ) -> Config {
273
+ Config :: default ( ) . merge( partial)
274
+ }
275
+ }
276
+
209
277
impl Config {
210
278
211
- fn fill_from_parsed_config( mut self , parsed: ParsedConfig ) -> Config {
279
+ /// Merge `partial` into `self, overwriting fields in `self` with any non-`None` fields
280
+ /// in `partial`.
281
+ pub fn merge( mut self , partial: & PartialConfig ) -> Config {
212
282
$(
213
- if let Some ( val) = parsed . $i {
283
+ if let Some ( val) = partial . $i {
214
284
self . $i = val;
215
285
}
216
286
) +
217
287
self
218
288
}
219
289
220
- pub fn from_toml( toml: & str ) -> Config {
221
- let parsed = toml. parse( ) . unwrap( ) ;
222
- let parsed_config: ParsedConfig = match toml:: decode( parsed) {
223
- Some ( decoded) => decoded,
224
- None => {
225
- println!( "Decoding config file failed. Config:\n {}" , toml) ;
226
- let parsed: toml:: Value = toml. parse( ) . unwrap( ) ;
227
- println!( "\n \n Parsed:\n {:?}" , parsed) ;
228
- panic!( ) ;
229
- }
230
- } ;
231
- Config :: default ( ) . fill_from_parsed_config( parsed_config)
232
- }
233
-
234
290
pub fn override_value( & mut self , key: & str , val: & str ) {
235
291
match key {
236
292
$(
@@ -347,3 +403,37 @@ create_config! {
347
403
write_mode: WriteMode , WriteMode :: Default ,
348
404
"What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage" ;
349
405
}
406
+
407
+ #[ cfg( test) ]
408
+ mod tests {
409
+ use super :: * ;
410
+ #[ test]
411
+ fn test_config_merge_overrides ( ) {
412
+ let config = Config :: default ( ) . merge ( & PartialConfig {
413
+ ideal_width : Some ( 37 ) ,
414
+ ..PartialConfig :: default ( )
415
+ } ) ;
416
+ assert_eq ! ( 37 , config. ideal_width) ;
417
+ }
418
+
419
+ #[ test]
420
+ fn test_partial_config_merge_overrides ( ) {
421
+ let mut config = PartialConfig :: default ( ) ;
422
+ config. merge ( & PartialConfig { ideal_width : Some ( 37 ) , ..PartialConfig :: default ( ) } ) ;
423
+ assert_eq ! ( Some ( 37 ) , config. ideal_width) ;
424
+ }
425
+
426
+ #[ test]
427
+ fn test_config_merge_does_not_override_if_none ( ) {
428
+ let mut config = Config { ideal_width : 37 , ..Config :: default ( ) } ;
429
+ config = config. merge ( & PartialConfig :: new ( ) ) ;
430
+ assert_eq ! ( 37 , config. ideal_width) ;
431
+ }
432
+
433
+ #[ test]
434
+ fn test_partial_config_merge_does_not_override_if_none ( ) {
435
+ let mut config = PartialConfig { ideal_width : Some ( 37 ) , ..PartialConfig :: default ( ) } ;
436
+ config. merge ( & PartialConfig :: new ( ) ) ;
437
+ assert_eq ! ( Some ( 37 ) , config. ideal_width) ;
438
+ }
439
+ }
0 commit comments