@@ -339,6 +339,57 @@ impl Ini {
339
339
Ok ( self . map . clone ( ) )
340
340
}
341
341
342
+ ///Loads a file from a defined path, parses it and applies it to the existing hashmap in our struct.
343
+ ///While `load()` will clear the existing `Map`, `load_and_append()` applies the new values on top of
344
+ ///the existing hashmap, preserving previous values.
345
+ ///## Example
346
+ ///```rust
347
+ ///use configparser::ini::Ini;
348
+ ///
349
+ ///let mut config = Ini::new();
350
+ ///config.load("tests/test.ini").unwrap();
351
+ ///config.load_and_append("tests/sys_cfg.ini").ok(); // we don't have to worry if this doesn't succeed
352
+ ///config.load_and_append("tests/user_cfg.ini").ok(); // we don't have to worry if this doesn't succeed
353
+ ///let map = config.get_map().unwrap();
354
+ /////Then, we can use standard hashmap functions like:
355
+ ///let values = map.get("values").unwrap();
356
+ ///```
357
+ ///Returns `Ok(map)` with a clone of the stored `Map` if no errors are thrown or else `Err(error_string)`.
358
+ ///Use `get_mut_map()` if you want a mutable reference.
359
+ pub fn load_and_append < T : AsRef < Path > > (
360
+ & mut self ,
361
+ path : T ,
362
+ ) -> Result < Map < String , Map < String , Option < String > > > , String > {
363
+ let loaded = match self . parse ( match fs:: read_to_string ( & path) {
364
+ Err ( why) => {
365
+ return Err ( format ! (
366
+ "couldn't read {}: {}" ,
367
+ & path. as_ref( ) . display( ) ,
368
+ why
369
+ ) )
370
+ }
371
+ Ok ( s) => s,
372
+ } ) {
373
+ Err ( why) => {
374
+ return Err ( format ! (
375
+ "couldn't read {}: {}" ,
376
+ & path. as_ref( ) . display( ) ,
377
+ why
378
+ ) )
379
+ }
380
+ Ok ( map) => map,
381
+ } ;
382
+
383
+ for ( section, section_map) in loaded. iter ( ) {
384
+ self . map
385
+ . entry ( section. clone ( ) )
386
+ . or_insert_with ( Map :: new)
387
+ . extend ( section_map. clone ( ) ) ;
388
+ }
389
+
390
+ Ok ( self . map . clone ( ) )
391
+ }
392
+
342
393
///Reads an input string, parses it and puts the hashmap into our struct.
343
394
///At one time, it only stores one configuration, so each call to `load()` or `read()` will clear the existing `Map`, if present.
344
395
///## Example
@@ -368,6 +419,52 @@ impl Ini {
368
419
Ok ( self . map . clone ( ) )
369
420
}
370
421
422
+ ///Reads an input string, parses it and applies it to the existing hashmap in our struct.
423
+ ///While `read()` and `load()` will clear the existing `Map`, `read_and_append()` applies the new
424
+ ///values on top of the existing hashmap, preserving previous values.
425
+ ///## Example
426
+ ///```rust
427
+ ///use configparser::ini::Ini;
428
+ ///
429
+ ///let mut config = Ini::new();
430
+ ///if let Err(why) = config.read(String::from(
431
+ /// "[2000s]
432
+ /// 2020 = bad
433
+ /// 2023 = better")) {
434
+ /// panic!("{}", why);
435
+ ///};
436
+ ///if let Err(why) = config.read_and_append(String::from(
437
+ /// "[2000s]
438
+ /// 2020 = terrible")) {
439
+ /// panic!("{}", why);
440
+ ///};
441
+ ///let map = config.get_map().unwrap();
442
+ ///let few_years_ago = map["2000s"]["2020"].clone().unwrap();
443
+ ///let this_year = map["2000s"]["2023"].clone().unwrap();
444
+ ///assert_eq!(few_years_ago, "terrible"); // value updated!
445
+ ///assert_eq!(this_year, "better"); // keeps old values!
446
+ ///```
447
+ ///Returns `Ok(map)` with a clone of the stored `Map` if no errors are thrown or else `Err(error_string)`.
448
+ ///Use `get_mut_map()` if you want a mutable reference.
449
+ pub fn read_and_append (
450
+ & mut self ,
451
+ input : String ,
452
+ ) -> Result < Map < String , Map < String , Option < String > > > , String > {
453
+ let loaded = match self . parse ( input) {
454
+ Err ( why) => return Err ( why) ,
455
+ Ok ( map) => map,
456
+ } ;
457
+
458
+ for ( section, section_map) in loaded. iter ( ) {
459
+ self . map
460
+ . entry ( section. clone ( ) )
461
+ . or_insert_with ( Map :: new)
462
+ . extend ( section_map. clone ( ) ) ;
463
+ }
464
+
465
+ Ok ( self . map . clone ( ) )
466
+ }
467
+
371
468
///Writes the current configuation to the specified path. If a file is not present, it is automatically created for you, if a file already
372
469
///exists, it is truncated and the configuration is written to it.
373
470
///## Example
@@ -963,6 +1060,48 @@ impl Ini {
963
1060
Ok ( self . map . clone ( ) )
964
1061
}
965
1062
1063
+ ///Loads a file from a defined path, parses it and applies it to the existing hashmap in our struct.
1064
+ ///While `load_async()` will clear the existing `Map`, `load_and_append_async()` applies the new values on top
1065
+ ///of the existing hashmap, preserving previous values.
1066
+ ///
1067
+ ///Usage is similar to `load_and_append`, but `.await` must be called after along with the usual async rules.
1068
+ ///
1069
+ ///Returns `Ok(map)` with a clone of the stored `Map` if no errors are thrown or else `Err(error_string)`.
1070
+ ///Use `get_mut_map()` if you want a mutable reference.
1071
+ pub async fn load_and_append_async < T : AsRef < AsyncPath > > (
1072
+ & mut self ,
1073
+ path : T ,
1074
+ ) -> Result < Map < String , Map < String , Option < String > > > , String > {
1075
+ let loaded = match self . parse ( match async_fs:: read_to_string ( & path) . await {
1076
+ Err ( why) => {
1077
+ return Err ( format ! (
1078
+ "couldn't read {}: {}" ,
1079
+ & path. as_ref( ) . display( ) ,
1080
+ why
1081
+ ) )
1082
+ }
1083
+ Ok ( s) => s,
1084
+ } ) {
1085
+ Err ( why) => {
1086
+ return Err ( format ! (
1087
+ "couldn't read {}: {}" ,
1088
+ & path. as_ref( ) . display( ) ,
1089
+ why
1090
+ ) )
1091
+ }
1092
+ Ok ( map) => map,
1093
+ } ;
1094
+
1095
+ for ( section, section_map) in loaded. iter ( ) {
1096
+ self . map
1097
+ . entry ( section. clone ( ) )
1098
+ . or_insert_with ( Map :: new)
1099
+ . extend ( section_map. clone ( ) ) ;
1100
+ }
1101
+
1102
+ Ok ( self . map . clone ( ) )
1103
+ }
1104
+
966
1105
///Writes the current configuation to the specified path asynchronously. If a file is not present, it is automatically created for you, if a file already
967
1106
///exists, it is truncated and the configuration is written to it.
968
1107
///
0 commit comments