feat: add lazy static

Closes #13
This commit is contained in:
Dmitriy Pleshevskiy 2020-02-08 15:09:58 +03:00
parent ee2f098f4d
commit 175798acf3
7 changed files with 232 additions and 30 deletions

View file

@ -14,8 +14,9 @@ criterion = "0.3.1"
lazy_static = "1.4.0" lazy_static = "1.4.0"
[features] [features]
default = ["meta_namespace"] default = ["meta_namespace", "static"]
meta_namespace = [] meta_namespace = []
static = ["itconfig/static"]
[[bench]] [[bench]]
name = "main_benches" name = "main_benches"

View file

@ -3,11 +3,13 @@ use std::env;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
#[macro_use]
extern crate itconfig;
fn setup_env_var(initial: &String) { fn setup_env_var(key: &'static str, initial: String) {
env::set_var("TEST", initial); env::set_var(key, initial);
} }
@ -26,33 +28,66 @@ fn lazy_get_env() -> u32 {
fn source_vs_lazy(c: &mut Criterion) { fn source_vs_lazy(c: &mut Criterion) {
let source = Fun::new("source", |b, initial: &String| { setup_env_var("TEST", "1".to_string());
setup_env_var(initial);
let int: u32 = initial.parse().unwrap();
let source = Fun::new("source", |b, _| {
b.iter(move || { b.iter(move || {
assert_eq!(source_get_env(), int) assert_eq!(source_get_env(), 1)
}) })
}); });
let lazy = Fun::new("lazy", |b, initial: &String| { let lazy = Fun::new("lazy", |b, _| {
setup_env_var(initial);
let int: u32 = initial.parse().unwrap();
b.iter(move || { b.iter(move || {
assert_eq!(lazy_get_env(), int); assert_eq!(lazy_get_env(), 1);
}) })
}); });
let funcs = vec![source, lazy]; c.bench_functions("get_env", vec![source, lazy], 0);
c.bench_functions("get_env", funcs, "1".to_string());
} }
fn source_macro_vs_lazy_macro(c: &mut Criterion) {
config! {
TEST: &'static str,
TEST_WITH_DEFAULT: &'static str => "default",
static LAZY_TEST: &'static str,
static LAZY_TEST_WITH_DEFAULT: &'static str => "default",
}
setup_env_var("TEST", "test".to_string());
setup_env_var("LAZY_TEST", "test".to_string());
let source = Fun::new("source", |b, _| {
b.iter(move || {
assert_eq!(cfg::TEST(), "test");
})
});
let lazy = Fun::new("lazy", |b, _| {
b.iter(move || {
assert_eq!(cfg::LAZY_TEST(), "test");
})
});
let source_with_default = Fun::new("source_with_default", |b, _| {
b.iter(move || {
assert_eq!(cfg::TEST_WITH_DEFAULT(), "default");
})
});
let lazy_with_default = Fun::new("lazy_with_default", |b, _| {
b.iter(move || {
assert_eq!(cfg::LAZY_TEST_WITH_DEFAULT(), "default");
})
});
let funcs = vec![source, lazy, source_with_default, lazy_with_default];
c.bench_functions("macro", funcs, 0);
}
criterion_group! { criterion_group! {
benches, benches,
source_vs_lazy, source_vs_lazy,
source_macro_vs_lazy_macro,
} }
criterion_main!(benches); criterion_main!(benches);

View file

@ -422,3 +422,51 @@ fn concatenated_environment_variable_in_namespace() {
); );
assert_eq!(env::var("CONCAT_ENVVAR"), Err(VarError::NotPresent)); assert_eq!(env::var("CONCAT_ENVVAR"), Err(VarError::NotPresent));
} }
#[test]
#[cfg(feature = "static")]
fn static_variables() {
config! {
static STATIC_STR => "test",
static STATIC_STRING: String => "test",
static STATIC_I8: i8 => 1,
static STATIC_I16: i16 => 1,
static STATIC_I32: i32 => 1,
static STATIC_I64: i64 => 1,
static STATIC_I128: i128 => 1,
static STATIC_ISIZE: isize => 1,
static STATIC_U8: u8 => 1,
static STATIC_U16: u16 => 1,
static STATIC_U32: u32 => 1,
static STATIC_U64: u64 => 1,
static STATIC_U128: u128 => 1,
static STATIC_USIZE: usize => 1,
static STATIC_F32: f32 => 1,
static STATIC_F64: f64 => 1,
static STATIC_CONCAT_VARIABLE < (
"static ",
STATIC_CONCAT_PART => "part",
),
}
cfg::init();
assert_eq!(cfg::STATIC_STR(), "test");
assert_eq!(cfg::STATIC_STRING(), "test".to_string());
assert_eq!(cfg::STATIC_I8(), 1);
assert_eq!(cfg::STATIC_I16(), 1);
assert_eq!(cfg::STATIC_I32(), 1);
assert_eq!(cfg::STATIC_I64(), 1);
assert_eq!(cfg::STATIC_I128(), 1);
assert_eq!(cfg::STATIC_ISIZE(), 1);
assert_eq!(cfg::STATIC_U8(), 1);
assert_eq!(cfg::STATIC_U16(), 1);
assert_eq!(cfg::STATIC_U32(), 1);
assert_eq!(cfg::STATIC_U64(), 1);
assert_eq!(cfg::STATIC_U128(), 1);
assert_eq!(cfg::STATIC_USIZE(), 1);
assert_eq!(cfg::STATIC_F32(), 1.0);
assert_eq!(cfg::STATIC_F64(), 1.0);
assert_eq!(cfg::STATIC_CONCAT_VARIABLE(), "static part".to_string())
}

View file

@ -1,6 +1,6 @@
[package] [package]
name = "itconfig" name = "itconfig"
version = "0.10.2" version = "0.11.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"]
@ -16,11 +16,14 @@ readme = "README.md"
[dependencies] [dependencies]
failure = { version = "0.1.6", features = ["derive"]} failure = { version = "0.1.6", features = ["derive"]}
lazy_static = { version = "1.4.0", optional = true }
serde_json = { version = "1.0.44", optional = true } serde_json = { version = "1.0.44", optional = true }
[features] [features]
default = ["macro", "primitives"] default = ["macro", "primitives", "static"]
macro = [] macro = []
static = ["lazy_static"]
array = ["serde_json"] array = ["serde_json"]

View file

@ -119,6 +119,15 @@ impl FromEnvString for String {
} }
impl FromEnvString for &'static str {
type Err = ();
fn from_env_string(s: &EnvString) -> Result<Self, Self::Err> {
Ok(Box::leak(s.0.clone().into_boxed_str()))
}
}
#[doc(hidden)] #[doc(hidden)]
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct EnvString(String); pub struct EnvString(String);

View file

@ -87,12 +87,14 @@
// Rustc lints. // Rustc lints.
#![deny(unused_imports)] //#![deny(unused_imports)]
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#[macro_use] #[macro_use]
extern crate failure; extern crate failure;
#[cfg(feature = "static")]
extern crate lazy_static;
mod enverr; mod enverr;
mod getenv; mod getenv;
@ -108,7 +110,7 @@ pub mod prelude {
#[cfg(feature = "macro")] #[cfg(feature = "macro")]
#[allow(unused_imports)] //#[allow(unused_imports)]
#[macro_use] #[macro_use]
mod r#macro; mod r#macro;
#[cfg(feature = "macro")] #[cfg(feature = "macro")]

View file

@ -301,6 +301,14 @@ macro_rules! __itconfig_parse_module {
} }
#[macro_export]
#[doc(hidden)]
macro_rules! __itconfig_get_ty_or_default {
() => { &'static str };
($ty:ty) => { $ty };
}
#[macro_export] #[macro_export]
#[doc(hidden)] #[doc(hidden)]
macro_rules! __itconfig_parse_variables { macro_rules! __itconfig_parse_variables {
@ -329,6 +337,30 @@ macro_rules! __itconfig_parse_variables {
} }
}; };
// Find static concatenated variable
(
tokens = [
$(#$meta:tt)*
static $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,
is_static = true,
},
tokens = [$($rest)*],
$($args)*
}
};
// Find concatenated variable // Find concatenated variable
( (
tokens = [ tokens = [
@ -346,17 +378,18 @@ macro_rules! __itconfig_parse_variables {
concat = [], concat = [],
name = $name, name = $name,
ty = String, ty = String,
is_static = false,
}, },
tokens = [$($rest)*], tokens = [$($rest)*],
$($args)* $($args)*
} }
}; };
// Find variable // Find static variable
( (
tokens = [ tokens = [
$(#$meta:tt)* $(#$meta:tt)*
$name:ident : $ty:ty$( => $default:expr)?, static $name:ident $(: $ty:ty)? $(=> $default:expr)?,
$($rest:tt)* $($rest:tt)*
], ],
$($args:tt)* $($args:tt)*
@ -368,7 +401,33 @@ macro_rules! __itconfig_parse_variables {
unparsed_concat = [], unparsed_concat = [],
concat = [], concat = [],
name = $name, name = $name,
ty = $ty, ty = __itconfig_get_ty_or_default!($($ty)?),
is_static = true,
$(default = $default,)?
},
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 = __itconfig_get_ty_or_default!($($ty)?),
is_static = false,
$(default = $default,)? $(default = $default,)?
}, },
tokens = [$($rest)*], tokens = [$($rest)*],
@ -523,6 +582,9 @@ macro_rules! __itconfig_impl_namespace {
meta = $var_meta:tt, meta = $var_meta:tt,
concat = $var_concat:tt, concat = $var_concat:tt,
name = $var_name:ident, name = $var_name:ident,
$(env_name = $env_name:expr,)?
ty = $ty:ty,
is_static = $is_static:ident,
$($variable:tt)* $($variable:tt)*
},)*], },)*],
namespaces = [$({ namespaces = [$({
@ -543,6 +605,8 @@ macro_rules! __itconfig_impl_namespace {
$(#$meta)* $(#$meta)*
pub mod $mod_name { pub mod $mod_name {
#![allow(non_snake_case)] #![allow(non_snake_case)]
#[cfg(feature = "static")]
use lazy_static::lazy_static;
$(__itconfig_impl_namespace! { $(__itconfig_impl_namespace! {
variables = $ns_variable, variables = $ns_variable,
@ -567,6 +631,9 @@ macro_rules! __itconfig_impl_namespace {
concat = $var_concat, concat = $var_concat,
name = $var_name, name = $var_name,
env_prefix = $env_prefix, env_prefix = $env_prefix,
$(env_name = $env_name,)?
ty = $ty,
is_static = $is_static,
$($variable)* $($variable)*
})* })*
} }
@ -630,37 +697,74 @@ macro_rules! __itconfig_variable {
// Add method for env variable // Add method for env variable
( (
meta = [$(#$meta:tt,)*], meta = $meta:tt,
concat = $concat:tt, concat = $concat:tt,
name = $name:ident, name = $name:ident,
env_prefix = $env_prefix:expr, env_prefix = $env_prefix:expr,
env_name = $env_name:expr, env_name = $env_name:expr,
ty = $ty:ty, ty = $ty:ty,
is_static = $is_static:ident,
$(default = $default:expr,)? $(default = $default:expr,)?
) => { ) => {
$(#$meta)* __itconfig_variable!(
pub fn $name() -> $ty { @wrap
__itconfig_variable! { is_static = $is_static,
meta = $meta,
name = $name,
ty = $ty,
value = __itconfig_variable!(
@inner @inner
concat = $concat, concat = $concat,
env_name = $env_name, env_name = $env_name,
$(default = $default,)? $(default = $default,)?
} ),
} );
}; };
// Wrap static variables
(
@wrap
is_static = true,
meta = [$(#$meta:tt,)*],
name = $name:ident,
ty = $ty:ty,
value = $value:expr,
) => (
$(#$meta)*
pub fn $name() -> $ty {
lazy_static! {
static ref $name: $ty = $value;
}
(*$name).clone()
}
);
// Wrap functions
(
@wrap
is_static = false,
meta = [$(#$meta:tt,)*],
name = $name:ident,
ty = $ty:ty,
value = $value:expr,
) => (
$(#$meta)*
pub fn $name() -> $ty { $value }
);
// Concatenate function body // Concatenate function body
( (
@inner @inner
concat = [$($concat:expr,)+], concat = [$($concat:expr,)+],
env_name = $env_name:expr, env_name = $env_name:expr,
$($args:tt)* $($args:tt)*
) => ( ) => ({
let value_parts: Vec<String> = vec!($($concat),+); let value_parts: Vec<String> = vec!($($concat),+);
let value = value_parts.join(""); let value = value_parts.join("");
std::env::set_var($env_name, value.as_str()); std::env::set_var($env_name, value.as_str());
value value
); });
// Env without default // Env without default
( (