@@ -75,9 +75,18 @@ pub use crate::error::Error;
75
75
/// A type result type specific to `envy::Errors`
76
76
pub type Result < T > = std:: result:: Result < T , Error > ;
77
77
78
- struct Vars < Iter > ( Iter )
78
+ #[ derive( Default ) ]
79
+ struct VarsOptions {
80
+ keep_names : bool ,
81
+ }
82
+
83
+ struct Vars < Iter >
79
84
where
80
- Iter : IntoIterator < Item = ( String , String ) > ;
85
+ Iter : IntoIterator < Item = ( String , String ) > ,
86
+ {
87
+ inner : Iter ,
88
+ options : VarsOptions ,
89
+ }
81
90
82
91
struct Val ( String , String ) ;
83
92
@@ -103,9 +112,14 @@ impl<Iter: Iterator<Item = (String, String)>> Iterator for Vars<Iter> {
103
112
type Item = ( VarName , Val ) ;
104
113
105
114
fn next ( & mut self ) -> Option < Self :: Item > {
106
- self . 0
107
- . next ( )
108
- . map ( |( k, v) | ( VarName ( k. to_lowercase ( ) ) , Val ( k, v) ) )
115
+ self . inner . next ( ) . map ( |( k, v) | {
116
+ let var_name = if self . options . keep_names {
117
+ k. clone ( )
118
+ } else {
119
+ k. to_lowercase ( )
120
+ } ;
121
+ ( VarName ( var_name) , Val ( k, v) )
122
+ } )
109
123
}
110
124
}
111
125
@@ -252,9 +266,15 @@ struct Deserializer<'de, Iter: Iterator<Item = (String, String)>> {
252
266
}
253
267
254
268
impl < ' de , Iter : Iterator < Item = ( String , String ) > > Deserializer < ' de , Iter > {
255
- fn new ( vars : Iter ) -> Self {
269
+ fn new (
270
+ vars : Iter ,
271
+ options : Option < VarsOptions > ,
272
+ ) -> Self {
256
273
Deserializer {
257
- inner : MapDeserializer :: new ( Vars ( vars) ) ,
274
+ inner : MapDeserializer :: new ( Vars {
275
+ inner : vars,
276
+ options : options. unwrap_or_default ( ) ,
277
+ } ) ,
258
278
}
259
279
}
260
280
}
@@ -306,7 +326,7 @@ where
306
326
T : de:: DeserializeOwned ,
307
327
Iter : IntoIterator < Item = ( String , String ) > ,
308
328
{
309
- T :: deserialize ( Deserializer :: new ( iter. into_iter ( ) ) ) . map_err ( |error| match error {
329
+ T :: deserialize ( Deserializer :: new ( iter. into_iter ( ) , None ) ) . map_err ( |error| match error {
310
330
Error :: MissingValue ( value) => Error :: MissingValue ( value. to_uppercase ( ) ) ,
311
331
_ => error,
312
332
} )
@@ -380,6 +400,39 @@ where
380
400
Prefixed ( prefix. into ( ) )
381
401
}
382
402
403
+ /// A type which keeps the serde field names
404
+ ///
405
+ /// These types are created with with the [keep_names](fn.keep_names.html) module function
406
+ pub struct KeepNames ;
407
+
408
+ impl KeepNames {
409
+ /// Deserializes a type based on prefixed env variables
410
+ pub fn from_env < T > ( & self ) -> Result < T >
411
+ where
412
+ T : de:: DeserializeOwned ,
413
+ {
414
+ self . from_iter ( env:: vars ( ) )
415
+ }
416
+
417
+ /// Deserializes a type based on prefixed (String, String) tuples
418
+ pub fn from_iter < Iter , T > (
419
+ & self ,
420
+ iter : Iter ,
421
+ ) -> Result < T >
422
+ where
423
+ T : de:: DeserializeOwned ,
424
+ Iter : IntoIterator < Item = ( String , String ) > ,
425
+ {
426
+ let options = VarsOptions { keep_names : true } ;
427
+ T :: deserialize ( Deserializer :: new ( iter. into_iter ( ) , Some ( options) ) )
428
+ }
429
+ }
430
+
431
+ /// Produces a instance of `KeepNames` for keeping the serde field names
432
+ pub fn keep_names ( ) -> KeepNames {
433
+ KeepNames { }
434
+ }
435
+
383
436
#[ cfg( test) ]
384
437
mod tests {
385
438
use super :: * ;
@@ -420,6 +473,15 @@ mod tests {
420
473
newtype : CustomNewType ,
421
474
}
422
475
476
+ #[ derive( Deserialize , Debug , PartialEq ) ]
477
+ pub struct CrazyFoo {
478
+ #[ serde( rename = "BaR" ) ]
479
+ bar : String ,
480
+ #[ serde( rename = "SCREAMING_BAZ" ) ]
481
+ screaming_baz : bool ,
482
+ zoom : Option < u16 > ,
483
+ }
484
+
423
485
#[ test]
424
486
fn deserialize_from_iter ( ) {
425
487
let data = vec ! [
@@ -546,4 +608,24 @@ mod tests {
546
608
Ok ( expected)
547
609
) ;
548
610
}
611
+
612
+ #[ test]
613
+ fn keep_names_from_iter ( ) {
614
+ let data = vec ! [
615
+ ( String :: from( "BaR" ) , String :: from( "test" ) ) ,
616
+ ( String :: from( "SCREAMING_BAZ" ) , String :: from( "true" ) ) ,
617
+ ( String :: from( "zoom" ) , String :: from( "8080" ) ) ,
618
+ ] ;
619
+ match keep_names ( ) . from_iter :: < _ , CrazyFoo > ( data) {
620
+ Ok ( actual) => assert_eq ! (
621
+ actual,
622
+ CrazyFoo {
623
+ bar: String :: from( "test" ) ,
624
+ screaming_baz: true ,
625
+ zoom: Some ( 8080 ) ,
626
+ }
627
+ ) ,
628
+ Err ( e) => panic ! ( "{:#?}" , e) ,
629
+ }
630
+ }
549
631
}
0 commit comments