use crate::{convert::maybe_invalid_unicode_vars_os, from_iter, Result};
use serde::de;
use std::env;
#[derive(Debug)]
pub struct CaseInsensitivePostfixed<'a>(&'a str);
impl<'a> CaseInsensitivePostfixed<'a> {
pub fn from_env<T>(&self) -> Result<T>
where
T: de::DeserializeOwned,
{
self.from_iter(env::vars())
}
pub fn from_os_env<T>(&self) -> Result<T>
where
T: de::DeserializeOwned,
{
self.from_iter(maybe_invalid_unicode_vars_os()?)
}
pub fn from_iter<T, Iter>(&self, iter: Iter) -> Result<T>
where
T: de::DeserializeOwned,
Iter: IntoIterator<Item = (String, String)>,
{
from_iter(iter.into_iter().filter_map(|(key, value)| {
let (lowercase_postfix, lowercase_key) =
(self.0.to_lowercase(), key.to_lowercase());
if lowercase_key.ends_with(&lowercase_postfix) {
Some((
lowercase_key
.trim_end_matches(&lowercase_postfix)
.to_owned(),
value,
))
} else {
None
}
}))
}
pub fn postfix(&self) -> &str {
self.0
}
}
pub fn case_insensitive_postfixed(postfix: &str) -> CaseInsensitivePostfixed<'_> {
CaseInsensitivePostfixed(postfix)
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
#[derive(Debug, Deserialize, PartialEq, Eq)]
struct Test {
key: String,
}
#[test]
fn test_case_insensitive_postfixed() {
env::set_var("KEY_APP", "value");
let postfixed = case_insensitive_postfixed("_app")
.from_env::<Test>()
.unwrap();
assert_eq!(
postfixed,
Test {
key: String::from("value")
}
)
}
}