feat: add namespace to macro
This commit is contained in:
parent
6abe819b35
commit
a5912eb99b
3 changed files with 150 additions and 22 deletions
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "itconfig"
|
name = "itconfig"
|
||||||
version = "0.2.3"
|
version = "0.3.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"]
|
||||||
|
|
|
@ -23,9 +23,7 @@
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! __impl_from_for_numbers {
|
macro_rules! __impl_from_for_numbers {
|
||||||
(
|
($($ty:ty),+) => {
|
||||||
$($ty:ty),+
|
|
||||||
) => {
|
|
||||||
$(
|
$(
|
||||||
impl From<EnvValue> for $ty {
|
impl From<EnvValue> for $ty {
|
||||||
fn from(env: EnvValue) -> Self {
|
fn from(env: EnvValue) -> Self {
|
||||||
|
@ -39,13 +37,7 @@ macro_rules! __impl_from_for_numbers {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct EnvValue(String);
|
pub struct EnvValue(String);
|
||||||
|
|
||||||
impl EnvValue {
|
|
||||||
pub fn new(string: String) -> Self {
|
|
||||||
Self(string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__impl_from_for_numbers![
|
__impl_from_for_numbers![
|
||||||
i8, i16, i32, i64, i128, isize,
|
i8, i16, i32, i64, i128, isize,
|
||||||
|
@ -85,21 +77,25 @@ impl From<EnvValue> for String {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[macro_use] extern crate itconfig;
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// # use std::env;
|
||||||
|
/// # env::set_var("DATABASE_URL", "postgres://u:p@localhost:5432/db");
|
||||||
/// config! {
|
/// config! {
|
||||||
/// DATABASE_URL: String,
|
/// DATABASE_URL: String,
|
||||||
/// }
|
/// }
|
||||||
/// # fn main () {}
|
/// # cfg::init()
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Config with default value
|
/// Config with default value
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[macro_use] extern crate itconfig;
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// # use std::env;
|
||||||
|
/// # env::set_var("DATABASE_URL", "postgres://u:p@localhost:5432/db");
|
||||||
/// config! {
|
/// config! {
|
||||||
/// DATABASE_URL: String,
|
/// DATABASE_URL: String,
|
||||||
/// HOST: String => "127.0.0.1".to_string(),
|
/// HOST: String => "127.0.0.1".to_string(),
|
||||||
/// }
|
/// }
|
||||||
/// # fn main () {}
|
/// # cfg::init()
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// By default itconfig lib creates module with 'cfg' name. But you can use simple meta instruction
|
/// By default itconfig lib creates module with 'cfg' name. But you can use simple meta instruction
|
||||||
|
@ -107,12 +103,38 @@ impl From<EnvValue> for String {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[macro_use] extern crate itconfig;
|
/// # #[macro_use] extern crate itconfig;
|
||||||
|
/// # use std::env;
|
||||||
|
/// env::set_var("DEBUG", "t");
|
||||||
|
///
|
||||||
/// config! {
|
/// config! {
|
||||||
/// #![mod_name = configuration]
|
/// #![mod_name = configuration]
|
||||||
///
|
///
|
||||||
/// DEBUG: bool,
|
/// DEBUG: bool,
|
||||||
/// }
|
/// }
|
||||||
/// # fn main () {}
|
///
|
||||||
|
/// configuration::init();
|
||||||
|
/// assert_eq!(configuration::DEBUG(), true);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// 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()
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
@ -185,6 +207,7 @@ macro_rules! __itconfig_parse_module {
|
||||||
__itconfig_parse_variables! {
|
__itconfig_parse_variables! {
|
||||||
tokens = $tokens,
|
tokens = $tokens,
|
||||||
variables = [],
|
variables = [],
|
||||||
|
namespaces = [],
|
||||||
module = {
|
module = {
|
||||||
name = $name,
|
name = $name,
|
||||||
},
|
},
|
||||||
|
@ -201,6 +224,27 @@ macro_rules! __itconfig_parse_module {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! __itconfig_parse_variables {
|
macro_rules! __itconfig_parse_variables {
|
||||||
|
// Find namespace
|
||||||
|
(
|
||||||
|
tokens = [
|
||||||
|
$ns_name:ident { $($ns_tokens:tt)* }
|
||||||
|
$($rest:tt)*
|
||||||
|
],
|
||||||
|
$($args:tt)*
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
tokens = [$($ns_tokens)*],
|
||||||
|
variables = [],
|
||||||
|
callback = {
|
||||||
|
current_namespace = {
|
||||||
|
name = $ns_name,
|
||||||
|
},
|
||||||
|
tokens = [$($rest)*],
|
||||||
|
$($args)*
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Find variable with default value
|
// Find variable with default value
|
||||||
(
|
(
|
||||||
tokens = [
|
tokens = [
|
||||||
|
@ -256,6 +300,34 @@ macro_rules! __itconfig_parse_variables {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Done parsing all variables of namespace
|
||||||
|
(
|
||||||
|
tokens = [],
|
||||||
|
variables = $ns_variables:tt,
|
||||||
|
callback = {
|
||||||
|
current_namespace = {
|
||||||
|
$($current_namespace:tt)*
|
||||||
|
},
|
||||||
|
tokens = $tokens:tt,
|
||||||
|
variables = $variables:tt,
|
||||||
|
namespaces = [$($namespaces:tt,)*],
|
||||||
|
$($args:tt)*
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
__itconfig_parse_variables! {
|
||||||
|
tokens = $tokens,
|
||||||
|
variables = $variables,
|
||||||
|
namespaces = [
|
||||||
|
$($namespaces,)*
|
||||||
|
{
|
||||||
|
variables = $ns_variables,
|
||||||
|
$($current_namespace)*
|
||||||
|
},
|
||||||
|
],
|
||||||
|
$($args)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Done parsing all variables
|
// Done parsing all variables
|
||||||
(
|
(
|
||||||
tokens = [],
|
tokens = [],
|
||||||
|
@ -276,9 +348,16 @@ macro_rules! __itconfig_parse_variables {
|
||||||
macro_rules! __itconfig_impl {
|
macro_rules! __itconfig_impl {
|
||||||
(
|
(
|
||||||
variables = [$({
|
variables = [$({
|
||||||
name = $name:ident,
|
name = $var_name:ident,
|
||||||
$($variable:tt)*
|
$($variable:tt)*
|
||||||
},)+],
|
},)*],
|
||||||
|
namespaces = [$({
|
||||||
|
variables = [$({
|
||||||
|
name = $ns_var_name:tt,
|
||||||
|
$($ns_variables:tt)*
|
||||||
|
},)*],
|
||||||
|
name = $ns_name:ident,
|
||||||
|
},)*],
|
||||||
module = {
|
module = {
|
||||||
name = $mod_name:ident,
|
name = $mod_name:ident,
|
||||||
},
|
},
|
||||||
|
@ -288,16 +367,37 @@ macro_rules! __itconfig_impl {
|
||||||
use std::env;
|
use std::env;
|
||||||
use $crate::EnvValue;
|
use $crate::EnvValue;
|
||||||
|
|
||||||
|
$(
|
||||||
|
pub mod $ns_name {
|
||||||
|
use std::env;
|
||||||
|
use $crate::EnvValue;
|
||||||
|
|
||||||
|
$(__itconfig_variable! {
|
||||||
|
name = $ns_var_name,
|
||||||
|
$($ns_variables)*
|
||||||
|
env_prefix = concat!(stringify!($ns_name), "_"),
|
||||||
|
})*
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
$($name();)+
|
$($var_name();)*
|
||||||
|
|
||||||
|
$($($ns_name::$ns_var_name();)*)*
|
||||||
}
|
}
|
||||||
|
|
||||||
$(__itconfig_variable! {
|
$(__itconfig_variable! {
|
||||||
name = $name,
|
name = $var_name,
|
||||||
$($variable)*
|
$($variable)*
|
||||||
})+
|
env_prefix = "",
|
||||||
|
})*
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Invalid syntax
|
||||||
|
($($tokens:tt)*) => {
|
||||||
|
__itconfig_invalid_syntax!();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -310,9 +410,10 @@ macro_rules! __itconfig_variable {
|
||||||
ty = $ty:ty,
|
ty = $ty:ty,
|
||||||
env_name = $env_name:expr,
|
env_name = $env_name:expr,
|
||||||
default = $default:expr,
|
default = $default:expr,
|
||||||
|
env_prefix = $env_prefix:expr,
|
||||||
) => {
|
) => {
|
||||||
pub fn $name() -> $ty {
|
pub fn $name() -> $ty {
|
||||||
env::var($env_name)
|
env::var(concat!($env_prefix, $env_name))
|
||||||
.map(|val| EnvValue::from(val).into())
|
.map(|val| EnvValue::from(val).into())
|
||||||
.unwrap_or_else(|_| $default)
|
.unwrap_or_else(|_| $default)
|
||||||
}
|
}
|
||||||
|
@ -323,15 +424,22 @@ macro_rules! __itconfig_variable {
|
||||||
name = $name:ident,
|
name = $name:ident,
|
||||||
ty = $ty:ty,
|
ty = $ty:ty,
|
||||||
env_name = $env_name:expr,
|
env_name = $env_name:expr,
|
||||||
|
env_prefix = $env_prefix:expr,
|
||||||
) => {
|
) => {
|
||||||
pub fn $name() -> $ty {
|
pub fn $name() -> $ty {
|
||||||
env::var($env_name)
|
env::var(concat!($env_prefix, $env_name))
|
||||||
.map(|val| EnvValue::from(val).into())
|
.map(|val| EnvValue::from(val).into())
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
panic!(format!(r#"Cannot read "{}" environment variable"#, $env_name))
|
panic!(format!(r#"Cannot read "{}" environment variable"#,
|
||||||
|
concat!($env_prefix, $env_name)))
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Invalid syntax
|
||||||
|
($($tokens:tt)*) => {
|
||||||
|
__itconfig_invalid_syntax!();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
|
#![feature(trace_macros)]
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate itconfig;
|
extern crate itconfig;
|
||||||
|
|
||||||
|
@ -120,4 +123,21 @@ fn change_config_module_name() {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(custom_config_name::DEBUG(), true);
|
assert_eq!(custom_config_name::DEBUG(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_namespace() {
|
||||||
|
config! {
|
||||||
|
DEBUG: bool => true,
|
||||||
|
|
||||||
|
POSTGRES {
|
||||||
|
HOST: bool => true,
|
||||||
|
PORT: bool => true,
|
||||||
|
USERNAME: bool => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(cfg::DEBUG(), true);
|
||||||
|
assert_eq!(cfg::POSTGRES::HOST(), true);
|
||||||
}
|
}
|
Reference in a new issue