Add built-in support for deserializing Data from the env

master
Paul Woolcock 6 years ago
parent b463bdeeef
commit b7b8379e10
  1. 4
      Cargo.toml
  2. 7
      src/errors.rs
  3. 81
      src/helpers/env.rs
  4. 12
      src/helpers/mod.rs
  5. 3
      src/lib.rs

@ -22,6 +22,7 @@ tap-reader = "1"
try_from = "0.3.2" try_from = "0.3.2"
toml = { version = "0.4.6", optional = true } toml = { version = "0.4.6", optional = true }
hyper-old-types = "0.11.0" hyper-old-types = "0.11.0"
envy = { version = "0.4.0", optional = true }
[dependencies.chrono] [dependencies.chrono]
version = "0.4" version = "0.4"
@ -30,7 +31,8 @@ features = ["serde"]
[features] [features]
default = [] default = []
json = [] json = []
all = ["toml", "json"] env = ["envy"]
all = ["toml", "json", "env"]
[build-dependencies] [build-dependencies]
skeptic = "0.13.3" skeptic = "0.13.3"

@ -1,5 +1,7 @@
use std::{error, fmt, io::Error as IoError}; use std::{error, fmt, io::Error as IoError};
#[cfg(feature = "env")]
use envy::Error as EnvyError;
use hyper_old_types::Error as HeaderParseError; use hyper_old_types::Error as HeaderParseError;
use reqwest::{header::ToStrError as HeaderStrError, Error as HttpError, StatusCode}; use reqwest::{header::ToStrError as HeaderStrError, Error as HttpError, StatusCode};
use serde_json::Error as SerdeError; use serde_json::Error as SerdeError;
@ -52,6 +54,9 @@ pub enum Error {
HeaderStrError(HeaderStrError), HeaderStrError(HeaderStrError),
/// Error parsing the http Link header /// Error parsing the http Link header
HeaderParseError(HeaderParseError), HeaderParseError(HeaderParseError),
#[cfg(feature = "env")]
/// Error deserializing from the environment
Envy(EnvyError),
/// Other errors /// Other errors
Other(String), Other(String),
} }
@ -89,6 +94,7 @@ impl error::Error for Error {
Error::TomlDe(ref e) => e.description(), Error::TomlDe(ref e) => e.description(),
Error::HeaderStrError(ref e) => e.description(), Error::HeaderStrError(ref e) => e.description(),
Error::HeaderParseError(ref e) => e.description(), Error::HeaderParseError(ref e) => e.description(),
Error::Envy(ref e) => e.description(),
Error::Other(ref e) => e, Error::Other(ref e) => e,
} }
} }
@ -128,6 +134,7 @@ from! {
#[cfg(feature = "toml")] TomlDeError, TomlDe, #[cfg(feature = "toml")] TomlDeError, TomlDe,
HeaderStrError, HeaderStrError, HeaderStrError, HeaderStrError,
HeaderParseError, HeaderParseError, HeaderParseError, HeaderParseError,
EnvyError, Envy,
String, Other, String, Other,
} }

@ -0,0 +1,81 @@
use envy;
use data::Data;
use Result;
/// Attempts to deserialize a Data struct from the environment
pub fn from_env() -> Result<Data> {
Ok(envy::from_env()?)
}
/// Attempts to deserialize a Data struct from the environment. All keys are
/// prefixed with the given prefix
pub fn from_env_prefixed(prefix: &str) -> Result<Data> {
Ok(envy::prefixed(prefix).from_env()?)
}
#[cfg(test)]
mod tests {
use super::*;
use std::{
env,
ops::FnOnce,
panic::{catch_unwind, UnwindSafe},
};
fn withenv<F: FnOnce() -> R + UnwindSafe, R>(prefix: Option<&'static str>, test: F) -> R {
env::set_var(makekey(prefix, "BASE"), "https://example.com");
env::set_var(makekey(prefix, "CLIENT_ID"), "adbc01234");
env::set_var(makekey(prefix, "CLIENT_SECRET"), "0987dcba");
env::set_var(makekey(prefix, "REDIRECT"), "urn:ietf:wg:oauth:2.0:oob");
env::set_var(makekey(prefix, "TOKEN"), "fedc5678");
let result = catch_unwind(test);
env::remove_var(makekey(prefix, "BASE"));
env::remove_var(makekey(prefix, "CLIENT_ID"));
env::remove_var(makekey(prefix, "CLIENT_SECRET"));
env::remove_var(makekey(prefix, "REDIRECT"));
env::remove_var(makekey(prefix, "TOKEN"));
fn makekey(prefix: Option<&'static str>, key: &str) -> String {
if let Some(prefix) = prefix {
format!("{}{}", prefix, key)
} else {
key.to_string()
}
}
result.expect("failed")
}
#[test]
fn test_from_env_no_prefix() {
let desered = withenv(None, || from_env()).expect("Couldn't deser");
assert_eq!(
desered,
Data {
base: "https://example.com".into(),
client_id: "adbc01234".into(),
client_secret: "0987dcba".into(),
redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
token: "fedc5678".into(),
}
);
}
#[test]
fn test_from_env_prefixed() {
let desered = withenv(Some("APP_"), || from_env_prefixed("APP_")).expect("Couldn't deser");
assert_eq!(
desered,
Data {
base: "https://example.com".into(),
client_id: "adbc01234".into(),
client_secret: "0987dcba".into(),
redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
token: "fedc5678".into(),
}
);
}
}

@ -22,5 +22,17 @@ pub mod toml;
/// ``` /// ```
pub mod json; pub mod json;
#[cfg(feature = "env")]
/// Helpers for deserializing a `Data` struct from the environment
///
/// In order to use this module, set the "env" feature in your Cargo.toml:
///
/// ```toml,ignore
/// [dependencies.elefren]
/// version = "0.18"
/// features = ["env"]
/// ```
pub mod env;
/// Helpers for working with the command line /// Helpers for working with the command line
pub mod cli; pub mod cli;

@ -58,6 +58,9 @@ extern crate tap_reader;
extern crate try_from; extern crate try_from;
extern crate url; extern crate url;
#[cfg(feature = "env")]
extern crate envy;
#[cfg(feature = "toml")] #[cfg(feature = "toml")]
extern crate toml as tomlcrate; extern crate toml as tomlcrate;

Loading…
Cancel
Save