Skip to content

Commit 8712d52

Browse files
authored
Merge pull request #72 from eliad-wiz/keep_names
support keeping the original serde field names
2 parents de73490 + ff9ece2 commit 8712d52

File tree

1 file changed

+90
-8
lines changed

1 file changed

+90
-8
lines changed

src/lib.rs

+90-8
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,18 @@ pub use crate::error::Error;
7575
/// A type result type specific to `envy::Errors`
7676
pub type Result<T> = std::result::Result<T, Error>;
7777

78-
struct Vars<Iter>(Iter)
78+
#[derive(Default)]
79+
struct VarsOptions {
80+
keep_names: bool,
81+
}
82+
83+
struct Vars<Iter>
7984
where
80-
Iter: IntoIterator<Item = (String, String)>;
85+
Iter: IntoIterator<Item = (String, String)>,
86+
{
87+
inner: Iter,
88+
options: VarsOptions,
89+
}
8190

8291
struct Val(String, String);
8392

@@ -103,9 +112,14 @@ impl<Iter: Iterator<Item = (String, String)>> Iterator for Vars<Iter> {
103112
type Item = (VarName, Val);
104113

105114
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+
})
109123
}
110124
}
111125

@@ -252,9 +266,15 @@ struct Deserializer<'de, Iter: Iterator<Item = (String, String)>> {
252266
}
253267

254268
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 {
256273
Deserializer {
257-
inner: MapDeserializer::new(Vars(vars)),
274+
inner: MapDeserializer::new(Vars {
275+
inner: vars,
276+
options: options.unwrap_or_default(),
277+
}),
258278
}
259279
}
260280
}
@@ -306,7 +326,7 @@ where
306326
T: de::DeserializeOwned,
307327
Iter: IntoIterator<Item = (String, String)>,
308328
{
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 {
310330
Error::MissingValue(value) => Error::MissingValue(value.to_uppercase()),
311331
_ => error,
312332
})
@@ -380,6 +400,39 @@ where
380400
Prefixed(prefix.into())
381401
}
382402

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+
383436
#[cfg(test)]
384437
mod tests {
385438
use super::*;
@@ -420,6 +473,15 @@ mod tests {
420473
newtype: CustomNewType,
421474
}
422475

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+
423485
#[test]
424486
fn deserialize_from_iter() {
425487
let data = vec![
@@ -546,4 +608,24 @@ mod tests {
546608
Ok(expected)
547609
);
548610
}
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+
}
549631
}

0 commit comments

Comments
 (0)