use crate::convert::maybe_invalid_unicode_vars_os;
use crate::{from_iter, Result};
use serde::de;
use std::{env, string::String};
#[derive(Debug)]
pub struct CaseInsensitivePrefixed<'a>(&'a str);
impl<'a> CaseInsensitivePrefixed<'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(|(k, v)| {
let lowercase_prefix = self.0.to_lowercase();
let lowercase_env_key = k.to_lowercase();
if lowercase_env_key.starts_with(&lowercase_prefix) {
Some((
lowercase_env_key
.trim_start_matches(&lowercase_prefix)
.to_owned(),
v,
))
} else {
None
}
}))
}
pub fn prefix(&self) -> &str {
self.0
}
}
pub fn case_insensitive_prefixed(prefix: &str) -> CaseInsensitivePrefixed<'_> {
CaseInsensitivePrefixed(prefix)
}
#[cfg(test)]
mod test_case_insensitive_prefixed {
use super::case_insensitive_prefixed;
use serde::Deserialize;
use std::env;
#[derive(Debug, Deserialize, PartialEq, Eq)]
struct Test {
key: String,
}
#[test]
fn test_case_insensitive_prefixed() {
env::set_var("APP_KEY", "value");
let prefixed = case_insensitive_prefixed("app_")
.from_env::<Test>()
.unwrap();
assert_eq!(
prefixed,
Test {
key: String::from("value")
}
)
}
}