commit
0aa258cf17
8 changed files with 1022 additions and 863 deletions
|
@ -1,10 +1,10 @@
|
||||||
[package]
|
[package]
|
||||||
name = "itconfig"
|
name = "itconfig"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
authors = ["Dmitriy Pleshevskiy <dmitriy@ideascup.me>"]
|
authors = ["Dmitriy Pleshevskiy <dmitriy@ideascup.me>"]
|
||||||
description = "Easy build a configs from environment variables and use it in globally."
|
description = "Easy build a configs from environment variables and use it in globally."
|
||||||
categories = ["config", "web-programming"]
|
categories = ["config", "web-programming"]
|
||||||
keywords = ["config", "env", "macro", "configuration", "environment"]
|
keywords = ["config", "env", "configuration", "environment", "macro"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/icetemple/itconfig-rs"
|
repository = "https://github.com/icetemple/itconfig-rs"
|
||||||
|
@ -19,3 +19,8 @@ travis-ci = { repository = "icetemple/itconfig-rs" }
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ['macro']
|
||||||
|
macro = []
|
||||||
|
|
||||||
|
|
92
itconfig/src/envstr.rs
Normal file
92
itconfig/src/envstr.rs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub trait ToEnvString {
|
||||||
|
fn to_env_string(&self) -> EnvString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub trait FromEnvString: Sized {
|
||||||
|
type Err;
|
||||||
|
|
||||||
|
fn from_env_string(s: &EnvString) -> Result<Self, Self::Err>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<T> ToEnvString for T
|
||||||
|
where
|
||||||
|
T: ToString
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn to_env_string(&self) -> EnvString {
|
||||||
|
EnvString(self.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! from_env_string_numbers_impl {
|
||||||
|
($($ty:ty),+) => {
|
||||||
|
$(
|
||||||
|
impl FromEnvString for $ty {
|
||||||
|
type Err = <$ty as FromStr>::Err;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_env_string(s: &EnvString) -> Result<Self, Self::Err> {
|
||||||
|
s.0.parse::<Self>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
from_env_string_numbers_impl![
|
||||||
|
i8, i16, i32, i64, i128, isize,
|
||||||
|
u8, u16, u32, u64, u128, usize,
|
||||||
|
f32, f64
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
impl FromEnvString for bool {
|
||||||
|
type Err = ();
|
||||||
|
|
||||||
|
fn from_env_string(s: &EnvString) -> Result<Self, Self::Err> {
|
||||||
|
match s.to_lowercase().as_str() {
|
||||||
|
"true" | "t" | "yes" | "y" | "on" | "1" => Ok(true),
|
||||||
|
_ => Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl FromEnvString for String {
|
||||||
|
type Err = ();
|
||||||
|
|
||||||
|
fn from_env_string(s: &EnvString) -> Result<Self, Self::Err> {
|
||||||
|
Ok(s.0.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct EnvString(String);
|
||||||
|
|
||||||
|
impl EnvString {
|
||||||
|
pub fn parse<T: FromEnvString>(&self) -> Result<T, T::Err> {
|
||||||
|
FromEnvString::from_env_string(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for EnvString {
|
||||||
|
type Target = String;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
141
itconfig/src/getenv.rs
Normal file
141
itconfig/src/getenv.rs
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
use std::env;
|
||||||
|
use crate::envstr::{EnvString, FromEnvString, ToEnvString};
|
||||||
|
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! env_panic {
|
||||||
|
(MissingVariable, $env_name:expr) => {
|
||||||
|
panic!(r#"Environment variable "{}" is missing"#, $env_name)
|
||||||
|
};
|
||||||
|
(FailedToParse, $env_name:expr) => {
|
||||||
|
panic!(r#"Failed to parse environment variable "{}""#, $env_name)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Try to read environment variable and parse to expected type. You may to put to argument
|
||||||
|
/// any type with `FromEnvString` trait.
|
||||||
|
///
|
||||||
|
/// Panics
|
||||||
|
/// ------
|
||||||
|
/// Application will panic if environment variable is missing or cannot parse variable to
|
||||||
|
/// expected type
|
||||||
|
///
|
||||||
|
/// Example
|
||||||
|
/// -------
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate itconfig;
|
||||||
|
/// # use itconfig::get_env;
|
||||||
|
/// use std::env;
|
||||||
|
///
|
||||||
|
/// fn main () {
|
||||||
|
/// env::set_var("DEBUG", "true");
|
||||||
|
///
|
||||||
|
/// let result: bool = get_env("DEBUG");
|
||||||
|
///
|
||||||
|
/// assert_eq!(result, true);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
pub fn get_env<T>(env_name: &str) -> T
|
||||||
|
where
|
||||||
|
T: FromEnvString
|
||||||
|
{
|
||||||
|
get_env_or(env_name, || env_panic!(MissingVariable, env_name))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// This function is similar as `get_env` but more safely. You can pass default value for
|
||||||
|
/// environment variable with `ToEnvString` trait.
|
||||||
|
///
|
||||||
|
/// Panics
|
||||||
|
/// ------
|
||||||
|
/// Application will panic if cannot parse variable to expected type
|
||||||
|
///
|
||||||
|
/// Example
|
||||||
|
/// -------
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate itconfig;
|
||||||
|
/// # use itconfig::get_env_or_default;
|
||||||
|
/// use std::env;
|
||||||
|
///
|
||||||
|
/// fn main () {
|
||||||
|
/// let result: bool = get_env_or_default("TESTING", "true");
|
||||||
|
/// assert_eq!(result, true);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
pub fn get_env_or_default<T, D>(env_name: &str, default: D) -> T
|
||||||
|
where
|
||||||
|
T: FromEnvString,
|
||||||
|
D: ToEnvString,
|
||||||
|
{
|
||||||
|
get_env_or(env_name, || default.to_env_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// This function is similar as `get_env_or_default` but if env variable is missed, will set
|
||||||
|
/// default value to environment variable.
|
||||||
|
///
|
||||||
|
/// Panics
|
||||||
|
/// ------
|
||||||
|
/// Application will panic if cannot parse variable to expected type
|
||||||
|
///
|
||||||
|
/// Example
|
||||||
|
/// -------
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate itconfig;
|
||||||
|
/// # use itconfig::get_env_or_set_default;
|
||||||
|
/// use std::env;
|
||||||
|
///
|
||||||
|
/// fn main () {
|
||||||
|
/// let result: bool = get_env_or_set_default("TESTING", "true");
|
||||||
|
/// assert_eq!(result, true);
|
||||||
|
///
|
||||||
|
/// let var = env::var("TESTING").unwrap();
|
||||||
|
/// assert_eq!(var, "true");
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
pub fn get_env_or_set_default<T, D>(env_name: &str, default: D) -> T
|
||||||
|
where
|
||||||
|
T: FromEnvString,
|
||||||
|
D: ToEnvString,
|
||||||
|
{
|
||||||
|
get_env_or(env_name, || {
|
||||||
|
let val = default.to_env_string();
|
||||||
|
env::set_var(env_name, val.as_str());
|
||||||
|
val
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// This function returns env variable as `EnvString` structure. You can pass callback for custom
|
||||||
|
/// default expression. Callback should return `EnvString` value or `panic!`
|
||||||
|
pub fn get_env_or<T, F>(env_name: &str, cb: F) -> T
|
||||||
|
where
|
||||||
|
T: FromEnvString,
|
||||||
|
F: FnOnce() -> EnvString
|
||||||
|
{
|
||||||
|
let env_str = env::var(env_name)
|
||||||
|
.map(|s| s.to_env_string())
|
||||||
|
.unwrap_or_else(|_| cb());
|
||||||
|
|
||||||
|
parse_env_variable(env_name, env_str)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
fn parse_env_variable<T>(env_name: &str, env_str: EnvString) -> T
|
||||||
|
where
|
||||||
|
T: FromEnvString
|
||||||
|
{
|
||||||
|
env_str
|
||||||
|
.parse::<T>()
|
||||||
|
.unwrap_or_else(|_| env_panic!(FailedToParse, env_name))
|
||||||
|
}
|
||||||
|
|
|
@ -1,861 +1,22 @@
|
||||||
//! # itconfig
|
// Rustc lints.
|
||||||
//!
|
#![deny(unused_imports)]
|
||||||
//! Simple configuration with macro for rust application.
|
|
||||||
//!
|
|
||||||
//!
|
|
||||||
//! ## Motivation
|
|
||||||
//!
|
|
||||||
//! I began to use rust with web programming experience where environment variables are widely used
|
|
||||||
//! and often there are more then 50 of them. First I looked at already created libraries.
|
|
||||||
//! But there it's necessary to initialise structure that needs to be moved to each function
|
|
||||||
//! where you need variable. It uses little bit memory, but configuration lifetime is as long
|
|
||||||
//! as application lifetime. Because of it I decided to create my own library.
|
|
||||||
//!
|
|
||||||
//!
|
|
||||||
//! ## Example usage
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! #[macro_use] extern crate itconfig;
|
|
||||||
//! use std::env;
|
|
||||||
//! // use dotenv::dotenv;
|
|
||||||
//!
|
|
||||||
//! config! {
|
|
||||||
//! DEBUG: bool => true,
|
|
||||||
//! HOST: String => "127.0.0.1",
|
|
||||||
//!
|
|
||||||
//! DATABASE_URL < (
|
|
||||||
//! "postgres://",
|
|
||||||
//! POSTGRES_USERNAME => "user",
|
|
||||||
//! ":",
|
|
||||||
//! POSTGRES_PASSWORD => "pass",
|
|
||||||
//! "@",
|
|
||||||
//! POSTGRES_HOST => "localhost:5432",
|
|
||||||
//! "/",
|
|
||||||
//! POSTGRES_DB => "test",
|
|
||||||
//! ),
|
|
||||||
//!
|
|
||||||
//! APP {
|
|
||||||
//! ARTICLE {
|
|
||||||
//! PER_PAGE: u32 => 15,
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! #[cfg(feature = "companies")]
|
|
||||||
//! COMPANY {
|
|
||||||
//! #[env_name = "INSTITUTIONS_PER_PAGE"]
|
|
||||||
//! PER_PAGE: u32 => 15,
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! FEATURE {
|
|
||||||
//! NEW_MENU: bool => false,
|
|
||||||
//!
|
|
||||||
//! COMPANY {
|
|
||||||
//! PROFILE: bool => false,
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn main () {
|
|
||||||
//! // dotenv().ok();
|
|
||||||
//! env::set_var("FEATURE_NEW_MENU", "t");
|
|
||||||
//!
|
|
||||||
//! cfg::init();
|
|
||||||
//! assert_eq!(cfg::HOST(), String::from("127.0.0.1"));
|
|
||||||
//! assert_eq!(cfg::DATABASE_URL(), String::from("postgres://user:pass@localhost:5432/test"));
|
|
||||||
//! assert_eq!(cfg::APP::ARTICLE::PER_PAGE(), 15);
|
|
||||||
//! assert_eq!(cfg::FEATURE::NEW_MENU(), true);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
mod getenv;
|
||||||
|
pub mod envstr;
|
||||||
|
|
||||||
|
pub use self::getenv::*;
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub use crate::envstr::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(feature = "macro")]
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
#[macro_use]
|
||||||
|
mod r#macro;
|
||||||
|
#[cfg(feature = "macro")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! __impl_from_for_numbers {
|
pub use r#macro::*;
|
||||||
($($ty:ty),+) => {
|
|
||||||
$(
|
|
||||||
impl From<EnvValue> for $ty {
|
|
||||||
fn from(env: EnvValue) -> Self {
|
|
||||||
env.0.parse::<Self>().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct EnvValue(String);
|
|
||||||
|
|
||||||
__impl_from_for_numbers![
|
|
||||||
i8, i16, i32, i64, i128, isize,
|
|
||||||
u8, u16, u32, u64, u128, usize,
|
|
||||||
f32, f64
|
|
||||||
];
|
|
||||||
|
|
||||||
impl From<EnvValue> for bool {
|
|
||||||
fn from(env: EnvValue) -> Self {
|
|
||||||
match env.0.to_lowercase().as_str() {
|
|
||||||
"true" | "1" | "t" | "on" => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<String> for EnvValue {
|
|
||||||
fn from(val: String) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<EnvValue> for String {
|
|
||||||
fn from(env: EnvValue) -> Self {
|
|
||||||
env.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Creates new public mod with function fo get each environment variable of mapping.
|
|
||||||
///
|
|
||||||
/// All variables are required and program will panic if some variables haven't value, but you
|
|
||||||
/// can add default value for specific variable.
|
|
||||||
///
|
|
||||||
/// Starts with v0.6.0 if you don't have an optional variable, the variable is set automatically.
|
|
||||||
///
|
|
||||||
/// Example usage
|
|
||||||
/// -------------
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// # use std::env;
|
|
||||||
/// # env::set_var("DATABASE_URL", "postgres://u:p@localhost:5432/db");
|
|
||||||
/// config! {
|
|
||||||
/// DATABASE_URL: String,
|
|
||||||
/// }
|
|
||||||
/// # cfg::init()
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Config with default value
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// # use std::env;
|
|
||||||
/// # env::set_var("DATABASE_URL", "postgres://u:p@localhost:5432/db");
|
|
||||||
/// config! {
|
|
||||||
/// DATABASE_URL: String,
|
|
||||||
/// HOST: String => "127.0.0.1",
|
|
||||||
/// }
|
|
||||||
/// # cfg::init()
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// By default itconfig lib creates module with 'cfg' name. But you can use simple meta instruction
|
|
||||||
/// if you want to rename module. In the example below we renamed module to 'configuration'
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// # use std::env;
|
|
||||||
/// env::set_var("DEBUG", "t");
|
|
||||||
///
|
|
||||||
/// config! {
|
|
||||||
/// #![mod_name = configuration]
|
|
||||||
///
|
|
||||||
/// DEBUG: bool,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// configuration::init();
|
|
||||||
/// assert_eq!(configuration::DEBUG(), true);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Namespaces
|
|
||||||
/// ----------
|
|
||||||
///
|
|
||||||
/// You can use namespaces for env variables
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// # use std::env;
|
|
||||||
/// env::set_var("DEBUG", "t");
|
|
||||||
/// env::set_var("DATABASE_USERNAME", "user");
|
|
||||||
/// env::set_var("DATABASE_PASSWORD", "pass");
|
|
||||||
/// env::set_var("DATABASE_HOST", "localhost");
|
|
||||||
///
|
|
||||||
/// config! {
|
|
||||||
/// DEBUG: bool,
|
|
||||||
/// DATABASE {
|
|
||||||
/// USERNAME: String,
|
|
||||||
/// PASSWORD: String,
|
|
||||||
/// HOST: String,
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// # cfg::init()
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Now you can use nested structure in namespaces without limits :)
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// config! {
|
|
||||||
/// FIRST {
|
|
||||||
/// SECOND {
|
|
||||||
/// THIRD {
|
|
||||||
/// FOO: bool => true,
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// # cfg::init();
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Namespaces supports custom meta
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// config! {
|
|
||||||
/// #[cfg(feature = "first")]
|
|
||||||
/// FIRST {
|
|
||||||
/// #[cfg(feature = "second")]
|
|
||||||
/// SECOND {
|
|
||||||
/// #[cfg(feature = "third")]
|
|
||||||
/// THIRD {
|
|
||||||
/// FOO: bool => true,
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// # cfg::init();
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Meta
|
|
||||||
/// ----
|
|
||||||
///
|
|
||||||
/// If you want to read custom env name for variable you can change it manually.
|
|
||||||
///
|
|
||||||
/// **A variable in the nameespace will lose environment prefix**
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// # use std::env;
|
|
||||||
/// env::set_var("MY_CUSTOM_NAME", "95");
|
|
||||||
///
|
|
||||||
/// config! {
|
|
||||||
/// #[env_name = "MY_CUSTOM_NAME"]
|
|
||||||
/// PER_PAGE: i32,
|
|
||||||
///
|
|
||||||
/// APP {
|
|
||||||
/// #[env_name = "MY_CUSTOM_NAME"]
|
|
||||||
/// RECIPES_PER_PAGE: i32,
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// cfg::init();
|
|
||||||
/// assert_eq!(cfg::PER_PAGE(), 95);
|
|
||||||
/// assert_eq!(cfg::APP::RECIPES_PER_PAGE(), 95);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Also you can add custom meta for each variable. For example feature configurations.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// config! {
|
|
||||||
/// #[cfg(feature = "postgres")]
|
|
||||||
/// DATABASE_URL: String,
|
|
||||||
///
|
|
||||||
/// #[cfg(not(feature = "postgres"))]
|
|
||||||
/// DATABASE_URL: String,
|
|
||||||
/// }
|
|
||||||
/// # fn main() {}
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Concatenate
|
|
||||||
/// -----------
|
|
||||||
///
|
|
||||||
/// Try to concatenate env variable or strings or both to you env variable. It's easy!
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// # use std::env;
|
|
||||||
/// env::set_var("POSTGRES_USERNAME", "user");
|
|
||||||
/// env::set_var("POSTGRES_PASSWORD", "pass");
|
|
||||||
///
|
|
||||||
/// config! {
|
|
||||||
/// DATABASE_URL < (
|
|
||||||
/// "postgres://",
|
|
||||||
/// POSTGRES_USERNAME,
|
|
||||||
/// ":",
|
|
||||||
/// POSTGRES_PASSWORD,
|
|
||||||
/// "@",
|
|
||||||
/// POSTGRES_HOST => "localhost:5432",
|
|
||||||
/// "/",
|
|
||||||
/// POSTGRES_DB => "test",
|
|
||||||
/// ),
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// cfg::init();
|
|
||||||
/// assert_eq!(cfg::DATABASE_URL(), "postgres://user:pass@localhost:5432/test".to_string())
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Concatinated variables can be only strings and support all features like namespaces and meta.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// config! {
|
|
||||||
/// CONCATED_NAMESPACE {
|
|
||||||
/// #[env_name = "DATABASE_URL"]
|
|
||||||
/// CONCAT_ENVVAR < (
|
|
||||||
/// "postgres://",
|
|
||||||
/// NOT_DEFINED_PG_USERNAME => "user",
|
|
||||||
/// ":",
|
|
||||||
/// NOT_DEFINED_PG_PASSWORD => "pass",
|
|
||||||
/// "@",
|
|
||||||
/// NOT_DEFINED_PG_HOST => "localhost:5432",
|
|
||||||
/// "/",
|
|
||||||
/// NOT_DEFINED_PG_DB => "test",
|
|
||||||
/// ),
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// cfg::init();
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// ---
|
|
||||||
///
|
|
||||||
/// This module will also contain helper method:
|
|
||||||
/// --------------------------------------------
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// pub fn init() {}
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Run this at the main function for check all required variables without default value.
|
|
||||||
///
|
|
||||||
/// Panics
|
|
||||||
/// ------
|
|
||||||
///
|
|
||||||
/// If you miss some required variables your application will panic at startup.
|
|
||||||
///
|
|
||||||
/// Examples
|
|
||||||
/// --------
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// #[macro_use] extern crate itconfig;
|
|
||||||
/// // use dotenv::dotenv;
|
|
||||||
///
|
|
||||||
/// config! {
|
|
||||||
/// DEBUG: bool => true,
|
|
||||||
/// HOST: String => "127.0.0.1",
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main () {
|
|
||||||
/// // dotenv().ok();
|
|
||||||
/// cfg::init();
|
|
||||||
/// assert_eq!(cfg::HOST(), String::from("127.0.0.1"));
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
#[macro_export(local_inner_macros)]
|
|
||||||
macro_rules! config {
|
|
||||||
($($tokens:tt)*) => {
|
|
||||||
__itconfig_parse_module! {
|
|
||||||
tokens = [$($tokens)*],
|
|
||||||
name = cfg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! __itconfig_invalid_syntax {
|
|
||||||
() => {
|
|
||||||
compile_error!(
|
|
||||||
"Invalid `config!` syntax. Please see the `config!` macro docs for more info.\
|
|
||||||
`https://docs.rs/itconfig/latest/itconfig/macro.config.html`"
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! __itconfig_parse_module {
|
|
||||||
// Find module name
|
|
||||||
(
|
|
||||||
tokens = [
|
|
||||||
#![mod_name = $mod_name:ident]
|
|
||||||
$($rest:tt)*
|
|
||||||
],
|
|
||||||
name = $ignore:tt,
|
|
||||||
) => {
|
|
||||||
__itconfig_parse_module! {
|
|
||||||
tokens = [$($rest)*],
|
|
||||||
name = $mod_name,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Done parsing module
|
|
||||||
(
|
|
||||||
tokens = $tokens:tt,
|
|
||||||
name = $name:tt,
|
|
||||||
) => {
|
|
||||||
__itconfig_parse_variables! {
|
|
||||||
tokens = $tokens,
|
|
||||||
variables = [],
|
|
||||||
namespaces = [],
|
|
||||||
module = {
|
|
||||||
env_prefix = "",
|
|
||||||
name = $name,
|
|
||||||
meta = [],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invalid syntax
|
|
||||||
($($tokens:tt)*) => {
|
|
||||||
__itconfig_invalid_syntax!();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! __itconfig_parse_variables {
|
|
||||||
// Find namespace
|
|
||||||
(
|
|
||||||
tokens = [
|
|
||||||
$(#$meta:tt)*
|
|
||||||
$ns_name:ident { $($ns_tokens:tt)* }
|
|
||||||
$($rest:tt)*
|
|
||||||
],
|
|
||||||
$($args:tt)*
|
|
||||||
) => {
|
|
||||||
__itconfig_parse_variables! {
|
|
||||||
tokens = [$($ns_tokens)*],
|
|
||||||
variables = [],
|
|
||||||
namespaces = [],
|
|
||||||
module = {
|
|
||||||
env_prefix = concat!(stringify!($ns_name), "_"),
|
|
||||||
name = $ns_name,
|
|
||||||
meta = [$(#$meta)*],
|
|
||||||
},
|
|
||||||
callback = {
|
|
||||||
tokens = [$($rest)*],
|
|
||||||
$($args)*
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find concatenated variable
|
|
||||||
(
|
|
||||||
tokens = [
|
|
||||||
$(#$meta:tt)*
|
|
||||||
$name:ident < ($($inner:tt)+),
|
|
||||||
$($rest:tt)*
|
|
||||||
],
|
|
||||||
$($args:tt)*
|
|
||||||
) => {
|
|
||||||
__itconfig_parse_variables! {
|
|
||||||
current_variable = {
|
|
||||||
unparsed_meta = [$(#$meta)*],
|
|
||||||
meta = [],
|
|
||||||
unparsed_concat = [$($inner)+],
|
|
||||||
concat = [],
|
|
||||||
name = $name,
|
|
||||||
ty = String,
|
|
||||||
},
|
|
||||||
tokens = [$($rest)*],
|
|
||||||
$($args)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find variable
|
|
||||||
(
|
|
||||||
tokens = [
|
|
||||||
$(#$meta:tt)*
|
|
||||||
$name:ident : $ty:ty$( => $default:expr)?,
|
|
||||||
$($rest:tt)*
|
|
||||||
],
|
|
||||||
$($args:tt)*
|
|
||||||
) => {
|
|
||||||
__itconfig_parse_variables! {
|
|
||||||
current_variable = {
|
|
||||||
unparsed_meta = [$(#$meta)*],
|
|
||||||
meta = [],
|
|
||||||
unparsed_concat = [],
|
|
||||||
concat = [],
|
|
||||||
name = $name,
|
|
||||||
ty = $ty,
|
|
||||||
$(default = $default,)?
|
|
||||||
},
|
|
||||||
tokens = [$($rest)*],
|
|
||||||
$($args)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find meta with custom env name
|
|
||||||
(
|
|
||||||
current_variable = {
|
|
||||||
unparsed_meta = [
|
|
||||||
#[env_name = $env_name:expr]
|
|
||||||
$($rest:tt)*
|
|
||||||
],
|
|
||||||
meta = $meta:tt,
|
|
||||||
unparsed_concat = $unparsed_concat:tt,
|
|
||||||
concat = $concat:tt,
|
|
||||||
name = $name:ident,
|
|
||||||
$($current_variable:tt)*
|
|
||||||
},
|
|
||||||
$($args:tt)*
|
|
||||||
) => {
|
|
||||||
__itconfig_parse_variables! {
|
|
||||||
current_variable = {
|
|
||||||
unparsed_meta = [$($rest)*],
|
|
||||||
meta = $meta,
|
|
||||||
unparsed_concat = $unparsed_concat,
|
|
||||||
concat = $concat,
|
|
||||||
name = $name,
|
|
||||||
env_name = $env_name,
|
|
||||||
$($current_variable)*
|
|
||||||
},
|
|
||||||
$($args)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find stranger meta
|
|
||||||
(
|
|
||||||
current_variable = {
|
|
||||||
unparsed_meta = [
|
|
||||||
#$stranger_meta:tt
|
|
||||||
$($rest:tt)*
|
|
||||||
],
|
|
||||||
meta = [$(#$meta:tt,)*],
|
|
||||||
$($current_variable:tt)*
|
|
||||||
},
|
|
||||||
$($args:tt)*
|
|
||||||
) => {
|
|
||||||
__itconfig_parse_variables! {
|
|
||||||
current_variable = {
|
|
||||||
unparsed_meta = [$($rest)*],
|
|
||||||
meta = [$(#$meta,)* #$stranger_meta,],
|
|
||||||
$($current_variable)*
|
|
||||||
},
|
|
||||||
$($args)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse concat params
|
|
||||||
(
|
|
||||||
current_variable = {
|
|
||||||
unparsed_meta = $unparsed_meta:tt,
|
|
||||||
meta = $meta:tt,
|
|
||||||
unparsed_concat = [
|
|
||||||
$concat_param:tt$( => $default:expr)?,
|
|
||||||
$($rest:tt)*
|
|
||||||
],
|
|
||||||
concat = [$($concat:expr,)*],
|
|
||||||
$($current_variable:tt)*
|
|
||||||
},
|
|
||||||
$($args:tt)*
|
|
||||||
) => {
|
|
||||||
__itconfig_parse_variables! {
|
|
||||||
current_variable = {
|
|
||||||
unparsed_meta = $unparsed_meta,
|
|
||||||
meta = $meta,
|
|
||||||
unparsed_concat = [$($rest)*],
|
|
||||||
concat = [$($concat,)* __itconfig_concat_param!($concat_param$( => $default)?),],
|
|
||||||
$($current_variable)*
|
|
||||||
},
|
|
||||||
$($args)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Done parsing variable
|
|
||||||
(
|
|
||||||
current_variable = {
|
|
||||||
unparsed_meta = [],
|
|
||||||
meta = $meta:tt,
|
|
||||||
unparsed_concat = [],
|
|
||||||
$($current_variable:tt)*
|
|
||||||
},
|
|
||||||
tokens = $tokens:tt,
|
|
||||||
variables = [$($variables:tt,)*],
|
|
||||||
$($args:tt)*
|
|
||||||
) => {
|
|
||||||
__itconfig_parse_variables! {
|
|
||||||
tokens = $tokens,
|
|
||||||
variables = [$($variables,)* { meta = $meta, $($current_variable)* },],
|
|
||||||
$($args)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Done parsing all variables of namespace
|
|
||||||
(
|
|
||||||
tokens = [],
|
|
||||||
variables = $ns_variables:tt,
|
|
||||||
namespaces = $ns_namespaces:tt,
|
|
||||||
module = $ns_module:tt,
|
|
||||||
callback = {
|
|
||||||
tokens = $tokens:tt,
|
|
||||||
variables = $variables:tt,
|
|
||||||
namespaces = [$($namespaces:tt,)*],
|
|
||||||
$($args:tt)*
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
__itconfig_parse_variables! {
|
|
||||||
tokens = $tokens,
|
|
||||||
variables = $variables,
|
|
||||||
namespaces = [
|
|
||||||
$($namespaces,)*
|
|
||||||
{
|
|
||||||
variables = $ns_variables,
|
|
||||||
namespaces = $ns_namespaces,
|
|
||||||
module = $ns_module,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
$($args)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Done parsing all variables
|
|
||||||
(
|
|
||||||
tokens = [],
|
|
||||||
$($args:tt)*
|
|
||||||
) => {
|
|
||||||
__itconfig_impl_namespace!($($args)*);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invalid syntax
|
|
||||||
($($tokens:tt)*) => {
|
|
||||||
__itconfig_invalid_syntax!();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! __itconfig_impl_namespace {
|
|
||||||
(
|
|
||||||
variables = [$({
|
|
||||||
meta = $var_meta:tt,
|
|
||||||
concat = $var_concat:tt,
|
|
||||||
name = $var_name:ident,
|
|
||||||
$($variable:tt)*
|
|
||||||
},)*],
|
|
||||||
namespaces = [$({
|
|
||||||
variables = $ns_variable:tt,
|
|
||||||
namespaces = $ns_namespaces:tt,
|
|
||||||
module = {
|
|
||||||
env_prefix = $ns_env_prefix:expr,
|
|
||||||
name = $ns_mod_name:ident,
|
|
||||||
meta = [$(#$ns_meta:tt)*],
|
|
||||||
},
|
|
||||||
},)*],
|
|
||||||
module = {
|
|
||||||
env_prefix = $env_prefix:expr,
|
|
||||||
name = $mod_name:ident,
|
|
||||||
meta = [$(#$meta:tt)*],
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
$(#$meta)*
|
|
||||||
pub mod $mod_name {
|
|
||||||
#![allow(non_snake_case)]
|
|
||||||
use std::env;
|
|
||||||
use itconfig::EnvValue;
|
|
||||||
|
|
||||||
$(__itconfig_impl_namespace! {
|
|
||||||
variables = $ns_variable,
|
|
||||||
namespaces = $ns_namespaces,
|
|
||||||
module = {
|
|
||||||
env_prefix = $ns_env_prefix,
|
|
||||||
name = $ns_mod_name,
|
|
||||||
meta = [$(#$ns_meta)*],
|
|
||||||
},
|
|
||||||
})*
|
|
||||||
|
|
||||||
pub fn init() {
|
|
||||||
$($var_name();)*
|
|
||||||
$(
|
|
||||||
$(#$ns_meta)*
|
|
||||||
$ns_mod_name::init();
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
$(__itconfig_variable! {
|
|
||||||
meta = $var_meta,
|
|
||||||
concat = $var_concat,
|
|
||||||
name = $var_name,
|
|
||||||
env_prefix = $env_prefix,
|
|
||||||
$($variable)*
|
|
||||||
})*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invalid syntax
|
|
||||||
($($tokens:tt)*) => {
|
|
||||||
__itconfig_invalid_syntax!();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! __itconfig_concat_param {
|
|
||||||
// Find env parameter with default value
|
|
||||||
($env_name:ident => $default:expr) => {
|
|
||||||
__itconfig_variable_helper!(stringify!($env_name).to_uppercase(), $default, default)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find env parameter without default value
|
|
||||||
($env_name:ident) => {
|
|
||||||
env_or!(stringify!($env_name).to_uppercase())
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find string parameter
|
|
||||||
($str:expr) => ( $str.to_string() );
|
|
||||||
|
|
||||||
// Invalid syntax
|
|
||||||
($($tokens:tt)*) => {
|
|
||||||
__itconfig_invalid_syntax!();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! __itconfig_variable {
|
|
||||||
// Set default env name
|
|
||||||
(
|
|
||||||
meta = $meta:tt,
|
|
||||||
concat = $concat:tt,
|
|
||||||
name = $name:ident,
|
|
||||||
env_prefix = $env_prefix:expr,
|
|
||||||
ty = $ty:ty,
|
|
||||||
$($args:tt)*
|
|
||||||
) => {
|
|
||||||
__itconfig_variable! {
|
|
||||||
meta = $meta,
|
|
||||||
concat = $concat,
|
|
||||||
name = $name,
|
|
||||||
env_prefix = $env_prefix,
|
|
||||||
env_name = concat!($env_prefix, stringify!($name)).to_uppercase(),
|
|
||||||
ty = $ty,
|
|
||||||
$($args)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add method for concatenated variable
|
|
||||||
(
|
|
||||||
meta = [$(#$meta:tt,)*],
|
|
||||||
concat = [$($concat:expr,)+],
|
|
||||||
name = $name:ident,
|
|
||||||
env_prefix = $env_prefix:expr,
|
|
||||||
env_name = $env_name:expr,
|
|
||||||
ty = $ty:ty,
|
|
||||||
$($args:tt)*
|
|
||||||
) => {
|
|
||||||
$(#$meta)*
|
|
||||||
pub fn $name() -> $ty {
|
|
||||||
let value_parts: Vec<String> = vec!($($concat),+);
|
|
||||||
let value = value_parts.join("");
|
|
||||||
__itconfig_variable_helper!(@setenv $env_name, value)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add method for env variable
|
|
||||||
(
|
|
||||||
meta = [$(#$meta:tt,)*],
|
|
||||||
concat = [],
|
|
||||||
name = $name:ident,
|
|
||||||
env_prefix = $env_prefix:expr,
|
|
||||||
env_name = $env_name:expr,
|
|
||||||
ty = $ty:ty,
|
|
||||||
$(default = $default:expr,)?
|
|
||||||
) => {
|
|
||||||
$(#$meta)*
|
|
||||||
pub fn $name() -> $ty {
|
|
||||||
env_or!($env_name$(, $default)?)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invalid syntax
|
|
||||||
($($tokens:tt)*) => {
|
|
||||||
__itconfig_invalid_syntax!();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This macro returns environment variable by name and converts variable to desired type
|
|
||||||
/// or returns default value.
|
|
||||||
///
|
|
||||||
/// Panics
|
|
||||||
/// ------
|
|
||||||
/// If you don't pass default value, macro will panic
|
|
||||||
///
|
|
||||||
/// Examples
|
|
||||||
/// --------
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # #[macro_use] extern crate itconfig;
|
|
||||||
/// let url: String = env_or!("DATABASE_URL", "127.0.0.1".to_string());
|
|
||||||
/// assert_eq!(url, "127.0.0.1".to_string());
|
|
||||||
/// ```
|
|
||||||
#[macro_export(local_inner_macro)]
|
|
||||||
macro_rules! env_or {
|
|
||||||
// Env without default value
|
|
||||||
($env_name:expr) => {
|
|
||||||
__itconfig_variable_helper!($env_name, format!(r#"Cannot read "{}" environment variable"#, $env_name), panic);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Env with default value
|
|
||||||
($env_name:expr, $default:expr) => {
|
|
||||||
__itconfig_variable_helper!($env_name, $default, setenv);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invalid syntax
|
|
||||||
($($tokens:tt)*) => {
|
|
||||||
__itconfig_env_or_invalid_syntax!();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! __itconfig_env_or_invalid_syntax {
|
|
||||||
() => {
|
|
||||||
compile_error!(
|
|
||||||
"Invalid `env_or!` syntax. Please see the `env_or!` macro docs for more info.\
|
|
||||||
`https://docs.rs/itconfig/latest/itconfig/macro.env_or.html`"
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! __itconfig_variable_helper {
|
|
||||||
// Get env variable
|
|
||||||
($env_name:expr, $default:expr, $token:tt) => {{
|
|
||||||
use std::env;
|
|
||||||
use itconfig::EnvValue;
|
|
||||||
env::var($env_name)
|
|
||||||
.map(|val| __itconfig_variable_helper!(val))
|
|
||||||
.unwrap_or_else(|_| __itconfig_variable_helper!(@$token $env_name, $default))
|
|
||||||
}};
|
|
||||||
|
|
||||||
// Returns converted env variable
|
|
||||||
($(@default $env_name:expr,)? $default:expr) => {{
|
|
||||||
EnvValue::from($default.to_string()).into()
|
|
||||||
}};
|
|
||||||
|
|
||||||
// Set default value for env variable and returns default
|
|
||||||
(@setenv $env_name:expr, $default:expr) => {{
|
|
||||||
env::set_var($env_name, $default.to_string());
|
|
||||||
__itconfig_variable_helper!($default)
|
|
||||||
}};
|
|
||||||
|
|
||||||
// Make panic for env variable
|
|
||||||
(@panic $env_name:expr, $default:expr) => {
|
|
||||||
panic!($default);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invalid syntax
|
|
||||||
($($tokens:tt)*) => {
|
|
||||||
__itconfig_env_or_invalid_syntax!();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
706
itconfig/src/macro.rs
Normal file
706
itconfig/src/macro.rs
Normal file
|
@ -0,0 +1,706 @@
|
||||||
|
/// Creates new public mod with function fo get each environment variable of mapping.
|
||||||
|
///
|
||||||
|
/// All variables are required and program will panic if some variables haven't value, but you
|
||||||
|
/// can add default value for specific variable.
|
||||||
|
///
|
||||||
|
/// Starts with v0.6.0 if you don't have an optional variable, the variable is set automatically.
|
||||||
|
///
|
||||||
|
/// Example usage
|
||||||
|
/// -------------
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// # use std::env;
|
||||||
|
/// # env::set_var("DATABASE_URL", "postgres://u:p@localhost:5432/db");
|
||||||
|
/// config! {
|
||||||
|
/// DATABASE_URL: String,
|
||||||
|
/// }
|
||||||
|
/// # cfg::init()
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Config with default value
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// # use std::env;
|
||||||
|
/// # env::set_var("DATABASE_URL", "postgres://u:p@localhost:5432/db");
|
||||||
|
/// config! {
|
||||||
|
/// DATABASE_URL: String,
|
||||||
|
/// HOST: String => "127.0.0.1",
|
||||||
|
/// }
|
||||||
|
/// # cfg::init()
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// By default itconfig lib creates module with 'cfg' name. But you can use simple meta instruction
|
||||||
|
/// if you want to rename module. In the example below we renamed module to 'configuration'
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// # use std::env;
|
||||||
|
/// env::set_var("DEBUG", "t");
|
||||||
|
///
|
||||||
|
/// config! {
|
||||||
|
/// #![mod_name = configuration]
|
||||||
|
///
|
||||||
|
/// DEBUG: bool,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// configuration::init();
|
||||||
|
/// assert_eq!(configuration::DEBUG(), true);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Namespaces
|
||||||
|
/// ----------
|
||||||
|
///
|
||||||
|
/// You can use namespaces for env variables
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// # use std::env;
|
||||||
|
/// env::set_var("DEBUG", "t");
|
||||||
|
/// env::set_var("DATABASE_USERNAME", "user");
|
||||||
|
/// env::set_var("DATABASE_PASSWORD", "pass");
|
||||||
|
/// env::set_var("DATABASE_HOST", "localhost");
|
||||||
|
///
|
||||||
|
/// config! {
|
||||||
|
/// DEBUG: bool,
|
||||||
|
/// DATABASE {
|
||||||
|
/// USERNAME: String,
|
||||||
|
/// PASSWORD: String,
|
||||||
|
/// HOST: String,
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// # cfg::init()
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Now you can use nested structure in namespaces without limits :)
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// config! {
|
||||||
|
/// FIRST {
|
||||||
|
/// SECOND {
|
||||||
|
/// THIRD {
|
||||||
|
/// FOO: bool => true,
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// # cfg::init();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Namespaces supports custom meta
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// config! {
|
||||||
|
/// #[cfg(feature = "first")]
|
||||||
|
/// FIRST {
|
||||||
|
/// #[cfg(feature = "second")]
|
||||||
|
/// SECOND {
|
||||||
|
/// #[cfg(feature = "third")]
|
||||||
|
/// THIRD {
|
||||||
|
/// FOO: bool => true,
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// # cfg::init();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Meta
|
||||||
|
/// ----
|
||||||
|
///
|
||||||
|
/// If you want to read custom env name for variable you can change it manually.
|
||||||
|
///
|
||||||
|
/// **A variable in the nameespace will lose environment prefix**
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// # use std::env;
|
||||||
|
/// env::set_var("MY_CUSTOM_NAME", "95");
|
||||||
|
///
|
||||||
|
/// config! {
|
||||||
|
/// #[env_name = "MY_CUSTOM_NAME"]
|
||||||
|
/// PER_PAGE: i32,
|
||||||
|
///
|
||||||
|
/// APP {
|
||||||
|
/// #[env_name = "MY_CUSTOM_NAME"]
|
||||||
|
/// RECIPES_PER_PAGE: i32,
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// cfg::init();
|
||||||
|
/// assert_eq!(cfg::PER_PAGE(), 95);
|
||||||
|
/// assert_eq!(cfg::APP::RECIPES_PER_PAGE(), 95);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Also you can add custom meta for each variable. For example feature configurations.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// config! {
|
||||||
|
/// #[cfg(feature = "postgres")]
|
||||||
|
/// DATABASE_URL: String,
|
||||||
|
///
|
||||||
|
/// #[cfg(not(feature = "postgres"))]
|
||||||
|
/// DATABASE_URL: String,
|
||||||
|
/// }
|
||||||
|
/// # fn main() {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Concatenate
|
||||||
|
/// -----------
|
||||||
|
///
|
||||||
|
/// Try to concatenate env variable or strings or both to you env variable. It's easy!
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// # use std::env;
|
||||||
|
/// env::set_var("POSTGRES_USERNAME", "user");
|
||||||
|
/// env::set_var("POSTGRES_PASSWORD", "pass");
|
||||||
|
///
|
||||||
|
/// config! {
|
||||||
|
/// DATABASE_URL < (
|
||||||
|
/// "postgres://",
|
||||||
|
/// POSTGRES_USERNAME,
|
||||||
|
/// ":",
|
||||||
|
/// POSTGRES_PASSWORD,
|
||||||
|
/// "@",
|
||||||
|
/// POSTGRES_HOST => "localhost:5432",
|
||||||
|
/// "/",
|
||||||
|
/// POSTGRES_DB => "test",
|
||||||
|
/// ),
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// cfg::init();
|
||||||
|
/// assert_eq!(cfg::DATABASE_URL(), "postgres://user:pass@localhost:5432/test".to_string())
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Concatinated variables can be only strings and support all features like namespaces and meta.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// config! {
|
||||||
|
/// CONCATED_NAMESPACE {
|
||||||
|
/// #[env_name = "DATABASE_URL"]
|
||||||
|
/// CONCAT_ENVVAR < (
|
||||||
|
/// "postgres://",
|
||||||
|
/// NOT_DEFINED_PG_USERNAME => "user",
|
||||||
|
/// ":",
|
||||||
|
/// NOT_DEFINED_PG_PASSWORD => "pass",
|
||||||
|
/// "@",
|
||||||
|
/// NOT_DEFINED_PG_HOST => "localhost:5432",
|
||||||
|
/// "/",
|
||||||
|
/// NOT_DEFINED_PG_DB => "test",
|
||||||
|
/// ),
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// cfg::init();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ---
|
||||||
|
///
|
||||||
|
/// This module will also contain helper method:
|
||||||
|
/// --------------------------------------------
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// pub fn init() {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Run this at the main function for check all required variables without default value.
|
||||||
|
///
|
||||||
|
/// Panics
|
||||||
|
/// ------
|
||||||
|
///
|
||||||
|
/// If you miss some required variables your application will panic at startup.
|
||||||
|
///
|
||||||
|
/// Examples
|
||||||
|
/// --------
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// #[macro_use] extern crate itconfig;
|
||||||
|
/// // use dotenv::dotenv;
|
||||||
|
///
|
||||||
|
/// config! {
|
||||||
|
/// DEBUG: bool => true,
|
||||||
|
/// HOST: String => "127.0.0.1",
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn main () {
|
||||||
|
/// // dotenv().ok();
|
||||||
|
/// cfg::init();
|
||||||
|
/// assert_eq!(cfg::HOST(), String::from("127.0.0.1"));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
#[macro_export(local_inner_macros)]
|
||||||
|
macro_rules! config {
|
||||||
|
($($tokens:tt)*) => {
|
||||||
|
__itconfig_parse_module! {
|
||||||
|
tokens = [$($tokens)*],
|
||||||
|
name = cfg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! __itconfig_invalid_syntax {
|
||||||
|
() => {
|
||||||
|
compile_error!(
|
||||||
|
"Invalid `config!` syntax. Please see the `config!` macro docs for more info.\
|
||||||
|
`https://docs.rs/itconfig/latest/itconfig/macro.config.html`"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! __itconfig_parse_module {
|
||||||
|
// Find module name
|
||||||
|
(
|
||||||
|
tokens = [
|
||||||
|
#![mod_name = $mod_name:ident]
|
||||||
|
$($rest:tt)*
|
||||||
|
],
|
||||||
|
name = $ignore:tt,
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_module! {
|
||||||
|
tokens = [$($rest)*],
|
||||||
|
name = $mod_name,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Done parsing module
|
||||||
|
(
|
||||||
|
tokens = $tokens:tt,
|
||||||
|
name = $name:tt,
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
tokens = $tokens,
|
||||||
|
variables = [],
|
||||||
|
namespaces = [],
|
||||||
|
module = {
|
||||||
|
env_prefix = "",
|
||||||
|
name = $name,
|
||||||
|
meta = [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invalid syntax
|
||||||
|
($($tokens:tt)*) => {
|
||||||
|
__itconfig_invalid_syntax!();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! __itconfig_parse_variables {
|
||||||
|
// Find namespace
|
||||||
|
(
|
||||||
|
tokens = [
|
||||||
|
$(#$meta:tt)*
|
||||||
|
$ns_name:ident { $($ns_tokens:tt)* }
|
||||||
|
$($rest:tt)*
|
||||||
|
],
|
||||||
|
$($args:tt)*
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
tokens = [$($ns_tokens)*],
|
||||||
|
variables = [],
|
||||||
|
namespaces = [],
|
||||||
|
module = {
|
||||||
|
env_prefix = concat!(stringify!($ns_name), "_"),
|
||||||
|
name = $ns_name,
|
||||||
|
meta = [$(#$meta)*],
|
||||||
|
},
|
||||||
|
callback = {
|
||||||
|
tokens = [$($rest)*],
|
||||||
|
$($args)*
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find concatenated variable
|
||||||
|
(
|
||||||
|
tokens = [
|
||||||
|
$(#$meta:tt)*
|
||||||
|
$name:ident < ($($inner:tt)+),
|
||||||
|
$($rest:tt)*
|
||||||
|
],
|
||||||
|
$($args:tt)*
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
current_variable = {
|
||||||
|
unparsed_meta = [$(#$meta)*],
|
||||||
|
meta = [],
|
||||||
|
unparsed_concat = [$($inner)+],
|
||||||
|
concat = [],
|
||||||
|
name = $name,
|
||||||
|
ty = String,
|
||||||
|
},
|
||||||
|
tokens = [$($rest)*],
|
||||||
|
$($args)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find variable
|
||||||
|
(
|
||||||
|
tokens = [
|
||||||
|
$(#$meta:tt)*
|
||||||
|
$name:ident : $ty:ty$( => $default:expr)?,
|
||||||
|
$($rest:tt)*
|
||||||
|
],
|
||||||
|
$($args:tt)*
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
current_variable = {
|
||||||
|
unparsed_meta = [$(#$meta)*],
|
||||||
|
meta = [],
|
||||||
|
unparsed_concat = [],
|
||||||
|
concat = [],
|
||||||
|
name = $name,
|
||||||
|
ty = $ty,
|
||||||
|
$(default = $default,)?
|
||||||
|
},
|
||||||
|
tokens = [$($rest)*],
|
||||||
|
$($args)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find meta with custom env name
|
||||||
|
(
|
||||||
|
current_variable = {
|
||||||
|
unparsed_meta = [
|
||||||
|
#[env_name = $env_name:expr]
|
||||||
|
$($rest:tt)*
|
||||||
|
],
|
||||||
|
meta = $meta:tt,
|
||||||
|
unparsed_concat = $unparsed_concat:tt,
|
||||||
|
concat = $concat:tt,
|
||||||
|
name = $name:ident,
|
||||||
|
$($current_variable:tt)*
|
||||||
|
},
|
||||||
|
$($args:tt)*
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
current_variable = {
|
||||||
|
unparsed_meta = [$($rest)*],
|
||||||
|
meta = $meta,
|
||||||
|
unparsed_concat = $unparsed_concat,
|
||||||
|
concat = $concat,
|
||||||
|
name = $name,
|
||||||
|
env_name = $env_name,
|
||||||
|
$($current_variable)*
|
||||||
|
},
|
||||||
|
$($args)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find stranger meta
|
||||||
|
(
|
||||||
|
current_variable = {
|
||||||
|
unparsed_meta = [
|
||||||
|
#$stranger_meta:tt
|
||||||
|
$($rest:tt)*
|
||||||
|
],
|
||||||
|
meta = [$(#$meta:tt,)*],
|
||||||
|
$($current_variable:tt)*
|
||||||
|
},
|
||||||
|
$($args:tt)*
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
current_variable = {
|
||||||
|
unparsed_meta = [$($rest)*],
|
||||||
|
meta = [$(#$meta,)* #$stranger_meta,],
|
||||||
|
$($current_variable)*
|
||||||
|
},
|
||||||
|
$($args)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse concat params
|
||||||
|
(
|
||||||
|
current_variable = {
|
||||||
|
unparsed_meta = $unparsed_meta:tt,
|
||||||
|
meta = $meta:tt,
|
||||||
|
unparsed_concat = [
|
||||||
|
$concat_param:tt$( => $default:expr)?,
|
||||||
|
$($rest:tt)*
|
||||||
|
],
|
||||||
|
concat = [$($concat:expr,)*],
|
||||||
|
$($current_variable:tt)*
|
||||||
|
},
|
||||||
|
$($args:tt)*
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
current_variable = {
|
||||||
|
unparsed_meta = $unparsed_meta,
|
||||||
|
meta = $meta,
|
||||||
|
unparsed_concat = [$($rest)*],
|
||||||
|
concat = [$($concat,)* __itconfig_concat_param!($concat_param$( => $default)?),],
|
||||||
|
$($current_variable)*
|
||||||
|
},
|
||||||
|
$($args)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Done parsing variable
|
||||||
|
(
|
||||||
|
current_variable = {
|
||||||
|
unparsed_meta = [],
|
||||||
|
meta = $meta:tt,
|
||||||
|
unparsed_concat = [],
|
||||||
|
$($current_variable:tt)*
|
||||||
|
},
|
||||||
|
tokens = $tokens:tt,
|
||||||
|
variables = [$($variables:tt,)*],
|
||||||
|
$($args:tt)*
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
tokens = $tokens,
|
||||||
|
variables = [$($variables,)* { meta = $meta, $($current_variable)* },],
|
||||||
|
$($args)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Done parsing all variables of namespace
|
||||||
|
(
|
||||||
|
tokens = [],
|
||||||
|
variables = $ns_variables:tt,
|
||||||
|
namespaces = $ns_namespaces:tt,
|
||||||
|
module = $ns_module:tt,
|
||||||
|
callback = {
|
||||||
|
tokens = $tokens:tt,
|
||||||
|
variables = $variables:tt,
|
||||||
|
namespaces = [$($namespaces:tt,)*],
|
||||||
|
$($args:tt)*
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
tokens = $tokens,
|
||||||
|
variables = $variables,
|
||||||
|
namespaces = [
|
||||||
|
$($namespaces,)*
|
||||||
|
{
|
||||||
|
variables = $ns_variables,
|
||||||
|
namespaces = $ns_namespaces,
|
||||||
|
module = $ns_module,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
$($args)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Done parsing all variables
|
||||||
|
(
|
||||||
|
tokens = [],
|
||||||
|
$($args:tt)*
|
||||||
|
) => {
|
||||||
|
__itconfig_impl_namespace!($($args)*);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invalid syntax
|
||||||
|
($($tokens:tt)*) => {
|
||||||
|
__itconfig_invalid_syntax!();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! __itconfig_impl_namespace {
|
||||||
|
(
|
||||||
|
variables = [$({
|
||||||
|
meta = $var_meta:tt,
|
||||||
|
concat = $var_concat:tt,
|
||||||
|
name = $var_name:ident,
|
||||||
|
$($variable:tt)*
|
||||||
|
},)*],
|
||||||
|
namespaces = [$({
|
||||||
|
variables = $ns_variable:tt,
|
||||||
|
namespaces = $ns_namespaces:tt,
|
||||||
|
module = {
|
||||||
|
env_prefix = $ns_env_prefix:expr,
|
||||||
|
name = $ns_mod_name:ident,
|
||||||
|
meta = [$(#$ns_meta:tt)*],
|
||||||
|
},
|
||||||
|
},)*],
|
||||||
|
module = {
|
||||||
|
env_prefix = $env_prefix:expr,
|
||||||
|
name = $mod_name:ident,
|
||||||
|
meta = [$(#$meta:tt)*],
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
$(#$meta)*
|
||||||
|
pub mod $mod_name {
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
$(__itconfig_impl_namespace! {
|
||||||
|
variables = $ns_variable,
|
||||||
|
namespaces = $ns_namespaces,
|
||||||
|
module = {
|
||||||
|
env_prefix = $ns_env_prefix,
|
||||||
|
name = $ns_mod_name,
|
||||||
|
meta = [$(#$ns_meta)*],
|
||||||
|
},
|
||||||
|
})*
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
$($var_name();)*
|
||||||
|
$(
|
||||||
|
$(#$ns_meta)*
|
||||||
|
$ns_mod_name::init();
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
$(__itconfig_variable! {
|
||||||
|
meta = $var_meta,
|
||||||
|
concat = $var_concat,
|
||||||
|
name = $var_name,
|
||||||
|
env_prefix = $env_prefix,
|
||||||
|
$($variable)*
|
||||||
|
})*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invalid syntax
|
||||||
|
($($tokens:tt)*) => {
|
||||||
|
__itconfig_invalid_syntax!();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! __itconfig_concat_param {
|
||||||
|
// Find env parameter with default value
|
||||||
|
($env_name:ident => $default:expr) => (
|
||||||
|
itconfig::get_env_or_default(
|
||||||
|
stringify!($env_name).to_uppercase().as_str(),
|
||||||
|
$default
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find env parameter without default value
|
||||||
|
($env_name:ident) => (
|
||||||
|
itconfig::get_env(
|
||||||
|
stringify!($env_name).to_uppercase().as_str()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find string parameter
|
||||||
|
($str:expr) => ( $str.to_string() );
|
||||||
|
|
||||||
|
// Invalid syntax
|
||||||
|
($($tokens:tt)*) => {
|
||||||
|
__itconfig_invalid_syntax!();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! __itconfig_variable {
|
||||||
|
// Set default env name
|
||||||
|
(
|
||||||
|
meta = $meta:tt,
|
||||||
|
concat = $concat:tt,
|
||||||
|
name = $name:ident,
|
||||||
|
env_prefix = $env_prefix:expr,
|
||||||
|
ty = $ty:ty,
|
||||||
|
$($args:tt)*
|
||||||
|
) => {
|
||||||
|
__itconfig_variable! {
|
||||||
|
meta = $meta,
|
||||||
|
concat = $concat,
|
||||||
|
name = $name,
|
||||||
|
env_prefix = $env_prefix,
|
||||||
|
env_name = concat!($env_prefix, stringify!($name)).to_uppercase(),
|
||||||
|
ty = $ty,
|
||||||
|
$($args)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add method for concatenated variable
|
||||||
|
// (
|
||||||
|
// meta = [$(#$meta:tt,)*],
|
||||||
|
// concat = [$($concat:expr,)+],
|
||||||
|
// name = $name:ident,
|
||||||
|
// env_prefix = $env_prefix:expr,
|
||||||
|
// env_name = $env_name:expr,
|
||||||
|
// ty = $ty:ty,
|
||||||
|
// $($args:tt)*
|
||||||
|
// ) => {
|
||||||
|
// $(#$meta)*
|
||||||
|
// pub fn $name() -> $ty {
|
||||||
|
// let value_parts: Vec<String> = vec!($($concat),+);
|
||||||
|
// let value = value_parts.join("");
|
||||||
|
// __itconfig_variable_helper!(@setenv $env_name, value)
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// Add method for env variable
|
||||||
|
(
|
||||||
|
meta = [$(#$meta:tt,)*],
|
||||||
|
concat = $concat:tt,
|
||||||
|
name = $name:ident,
|
||||||
|
env_prefix = $env_prefix:expr,
|
||||||
|
env_name = $env_name:expr,
|
||||||
|
ty = $ty:ty,
|
||||||
|
$(default = $default:expr,)?
|
||||||
|
) => {
|
||||||
|
$(#$meta)*
|
||||||
|
pub fn $name() -> $ty {
|
||||||
|
__itconfig_variable! {
|
||||||
|
@inner
|
||||||
|
concat = $concat,
|
||||||
|
env_name = $env_name,
|
||||||
|
$(default = $default,)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(
|
||||||
|
@inner
|
||||||
|
concat = [$($concat:expr,)+],
|
||||||
|
env_name = $env_name:expr,
|
||||||
|
$($args:tt)*
|
||||||
|
) => (
|
||||||
|
let value_parts: Vec<String> = vec!($($concat),+);
|
||||||
|
let value = value_parts.join("");
|
||||||
|
std::env::set_var($env_name, value.as_str());
|
||||||
|
value
|
||||||
|
);
|
||||||
|
|
||||||
|
(
|
||||||
|
@inner
|
||||||
|
concat = [],
|
||||||
|
env_name = $env_name:expr,
|
||||||
|
) => (
|
||||||
|
itconfig::get_env($env_name.to_string().as_str())
|
||||||
|
);
|
||||||
|
|
||||||
|
(
|
||||||
|
@inner
|
||||||
|
concat = [],
|
||||||
|
env_name = $env_name:expr,
|
||||||
|
default = $default:expr,
|
||||||
|
) => (
|
||||||
|
itconfig::get_env_or_set_default(
|
||||||
|
$env_name.to_string().as_str(),
|
||||||
|
$default
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Invalid syntax
|
||||||
|
($($tokens:tt)*) => {
|
||||||
|
__itconfig_invalid_syntax!();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ extern crate itconfig;
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "Cannot read \"MISS_VARIABLE\" environment variable")]
|
#[should_panic(expected = "Environment variable \"MISS_VARIABLE\" is missing")]
|
||||||
fn should_panic_if_miss_env_variable() {
|
fn should_panic_if_miss_env_variable() {
|
||||||
config! {
|
config! {
|
||||||
MISS_VARIABLE: bool,
|
MISS_VARIABLE: bool,
|
||||||
|
@ -334,7 +334,7 @@ fn setting_default_concat_env_variable() {
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "Cannot read \"PG_USERNAME\" environment variable")]
|
#[should_panic(expected = "Environment variable \"PG_USERNAME\" is missing")]
|
||||||
fn concatenate_not_defined_environment_variables() {
|
fn concatenate_not_defined_environment_variables() {
|
||||||
config! {
|
config! {
|
||||||
DATABASE_URL < (
|
DATABASE_URL < (
|
||||||
|
|
23
itconfig_tests/tests/get_env.rs
Normal file
23
itconfig_tests/tests/get_env.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use std::env;
|
||||||
|
use itconfig::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Environment variable \"TEST_CASE_1\" is missing")]
|
||||||
|
fn missing_env_variable() {
|
||||||
|
get_env::<String>("TEST_CASE_1");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Failed to parse environment variable \"TEST_CASE_2\"")]
|
||||||
|
fn cannot_parse_env_variable() {
|
||||||
|
env::set_var("TEST_CASE_2", "30r");
|
||||||
|
get_env::<u32>("TEST_CASE_2");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_env_successfully() {
|
||||||
|
env::set_var("TEST_CASE_3", "30");
|
||||||
|
let a: u32 = get_env("TEST_CASE_3");
|
||||||
|
|
||||||
|
assert_eq!(a, 30);
|
||||||
|
}
|
31
itconfig_tests/tests/get_env_or_default.rs
Normal file
31
itconfig_tests/tests/get_env_or_default.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
use std::env;
|
||||||
|
use itconfig::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn missing_env_variable() {
|
||||||
|
let flag: bool = get_env_or_default("DEFAULT_TEST_CASE_1", "true");
|
||||||
|
assert_eq!(flag, true);
|
||||||
|
|
||||||
|
// let var: String = env::var("DEFAULT_TEST_CASE_1").unwrap();
|
||||||
|
// assert_eq!(var, "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Failed to parse environment variable \"DEFAULT_TEST_CASE_2\"")]
|
||||||
|
fn cannot_parse_env_variable() {
|
||||||
|
env::set_var("DEFAULT_TEST_CASE_2", "30r");
|
||||||
|
let _: u32 = get_env_or_default("DEFAULT_TEST_CASE_2", 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Failed to parse environment variable \"DEFAULT_TEST_CASE_2\"")]
|
||||||
|
fn cannot_parse_default_value() {
|
||||||
|
let _: u32 = get_env_or_default("DEFAULT_TEST_CASE_2", "30r");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_env_successfully() {
|
||||||
|
let a: u32 = get_env_or_default("DEFAULT_TEST_CASE_3", 30);
|
||||||
|
|
||||||
|
assert_eq!(a, 30);
|
||||||
|
}
|
Reference in a new issue