Format code using 'cargo fmt'

This commit is contained in:
Atul Bhosale 2020-07-02 23:24:17 +05:30
parent 3fc2c9ab5f
commit 59cd2f9903
No known key found for this signature in database
GPG Key ID: 9CE70EE4DDBEB4A7
16 changed files with 133 additions and 186 deletions

View File

@ -1,9 +1,8 @@
use super::config;
use diesel::prelude::*;
use diesel::pg::PgConnection;
use diesel::prelude::*;
pub fn establish_connection() -> PgConnection {
let database_url = config::DATABASE_URL();
PgConnection::establish(database_url)
.expect(&format!("Error connecting to {}", database_url))
PgConnection::establish(database_url).expect(&format!("Error connecting to {}", database_url))
}

View File

@ -5,17 +5,15 @@ mod db;
mod models;
mod schema;
use itconfig::config;
use dotenv::dotenv;
use diesel::prelude::*;
use crate::models::*;
use diesel::prelude::*;
use dotenv::dotenv;
use itconfig::config;
config! {
DATABASE_URL,
}
fn main() {
dotenv().ok();
config::init();
@ -32,12 +30,12 @@ fn main() {
}
}
fn get_posts(connection: &PgConnection) -> Vec<Post> {
use crate::schema::posts::dsl::*;
posts.filter(published.eq(true))
posts
.filter(published.eq(true))
.limit(5)
.get_results::<Post>(connection)
.expect("Error loading posts")
}
}

View File

@ -4,4 +4,4 @@ pub struct Post {
pub title: String,
pub body: String,
pub published: bool,
}
}

View File

@ -1,10 +1,9 @@
use itconfig::config;
use bytes::buf::BufExt;
use futures_util::{stream, StreamExt};
use hyper::client::HttpConnector;
use hyper::service::{make_service_fn, service_fn};
use hyper::{header, Body, Client, Method, Request, Response, Server, StatusCode};
use itconfig::config;
config! {
HYPER {
@ -25,17 +24,14 @@ config! {
}
}
type GenericError = Box<dyn std::error::Error + Send + Sync>;
type HyperResult<T> = std::result::Result<T, GenericError>;
const INDEX: &'static [u8] = b"<a href=\"test.html\">test.html</a>";
const INTERNAL_SERVER_ERROR: &'static [u8] = b"Internal Server Error";
const NOTFOUND: &'static [u8] = b"Not Found";
const POST_DATA: &'static str = r#"{"original": "data"}"#;
async fn client_request_response(client: &Client<HttpConnector>) -> HyperResult<Response<Body>> {
let req = Request::builder()
.method(Method::POST)

View File

@ -13,7 +13,6 @@ config! {
}
}
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
@ -25,4 +24,4 @@ fn main() {
rocket::ignite()
.mount(config::ROCKET::BASE_URL(), routes![index])
.launch();
}
}

View File

@ -1,6 +1,5 @@
use proc_macro2::TokenStream as TokenStream2;
use syn::{Type, Expr, Ident, Attribute};
use syn::{Attribute, Expr, Ident, Type};
pub struct RootNamespace {
pub name: Option<Ident>,
@ -9,7 +8,6 @@ pub struct RootNamespace {
pub meta: Vec<Attribute>,
}
pub struct Namespace {
pub name: Ident,
pub variables: Vec<Variable>,
@ -18,7 +16,6 @@ pub struct Namespace {
pub meta: Vec<Attribute>,
}
pub struct Variable {
pub is_static: bool,
pub name: Ident,

View File

@ -1,24 +1,23 @@
use crate::ast::*;
use quote::{quote, ToTokens, TokenStreamExt};
use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, ToTokens, TokenStreamExt};
fn vec_to_token_stream_2<T>(input: &Vec<T>) -> Vec<TokenStream2>
where T: ToTokens
where
T: ToTokens,
{
input.iter()
.map(|ns| ns.into_token_stream())
.collect()
input.iter().map(|ns| ns.into_token_stream()).collect()
}
impl ToTokens for RootNamespace {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let name = &self.name;
let variables = vec_to_token_stream_2(&self.variables);
let namespaces = vec_to_token_stream_2(&self.namespaces);
let init_variables = self.variables.iter()
let init_variables = self
.variables
.iter()
.map(|var| {
let name = &var.name;
let var_meta = vec_to_token_stream_2(&var.meta);
@ -29,7 +28,9 @@ impl ToTokens for RootNamespace {
)
})
.collect::<Vec<TokenStream2>>();
let init_namespaces = self.namespaces.iter()
let init_namespaces = self
.namespaces
.iter()
.map(|ns| {
let name = &ns.name;
let ns_meta = vec_to_token_stream_2(&ns.meta);
@ -43,13 +44,12 @@ impl ToTokens for RootNamespace {
let inner_meta: Vec<TokenStream2> = if name.is_none() {
vec![]
} else if self.meta.is_empty() {
} else if self.meta.is_empty() {
vec![quote!(#![allow(non_snake_case)])]
} else {
vec_to_token_stream_2(&self.meta)
};
let inner_rules = quote! {
#(#inner_meta)*
@ -63,20 +63,17 @@ impl ToTokens for RootNamespace {
}
};
tokens.append_all(
match self.name.as_ref() {
None => inner_rules,
Some(name) => quote! {
pub mod #name {
#inner_rules
}
tokens.append_all(match self.name.as_ref() {
None => inner_rules,
Some(name) => quote! {
pub mod #name {
#inner_rules
}
}
);
},
});
}
}
impl ToTokens for Namespace {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let name = &self.name;
@ -84,7 +81,9 @@ impl ToTokens for Namespace {
let namespaces = vec_to_token_stream_2(&self.namespaces);
let meta = vec_to_token_stream_2(&self.meta);
let init_variables = self.variables.iter()
let init_variables = self
.variables
.iter()
.map(|var| {
let name = &var.name;
let var_meta = vec_to_token_stream_2(&var.meta);
@ -95,7 +94,9 @@ impl ToTokens for Namespace {
)
})
.collect::<Vec<TokenStream2>>();
let init_namespaces = self.namespaces.iter()
let init_namespaces = self
.namespaces
.iter()
.map(|ns| {
let name = &ns.name;
let ns_meta = vec_to_token_stream_2(&ns.meta);
@ -123,12 +124,13 @@ impl ToTokens for Namespace {
}
}
impl ToTokens for Variable {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let ty = &self.ty;
let name = &self.name;
let env_name = &self.env_name.clone()
let env_name = &self
.env_name
.clone()
.unwrap_or(name.to_string().to_uppercase());
let meta = vec_to_token_stream_2(&self.meta);
@ -167,4 +169,4 @@ impl ToTokens for Variable {
));
}
}
}
}

View File

@ -1,16 +1,15 @@
#![recursion_limit = "256"]
mod ast;
mod parse;
mod expand;
mod parse;
extern crate proc_macro;
extern crate proc_macro2;
use self::proc_macro::TokenStream;
use ast::RootNamespace;
use quote::ToTokens;
use syn::parse_macro_input;
use ast::RootNamespace;
/// ### _This API requires the following crate features to be activated: `macro`_
///
@ -335,4 +334,4 @@ use ast::RootNamespace;
pub fn config(input: TokenStream) -> TokenStream {
let namespace = parse_macro_input!(input as RootNamespace);
namespace.into_token_stream().into()
}
}

View File

@ -1,43 +1,42 @@
use crate::ast::*;
use syn::parse::{Parse, ParseStream, Result, ParseBuffer};
use syn::token::{FatArrow, Comma, Colon, Brace, Lt};
use syn::{braced, parenthesized, Type, Expr, Token, Lit, Attribute, Meta, MetaNameValue, Error, parse_str, MetaList, NestedMeta};
use proc_macro2::{Ident, Span, TokenStream as TokenStream2};
use syn::ext::IdentExt;
use quote::quote;
use syn::ext::IdentExt;
use syn::parse::{Parse, ParseBuffer, ParseStream, Result};
use syn::token::{Brace, Colon, Comma, FatArrow, Lt};
use syn::{
braced, parenthesized, parse_str, Attribute, Error, Expr, Lit, Meta, MetaList, MetaNameValue,
NestedMeta, Token, Type,
};
fn fill_env_prefix(
prefix: String
) -> Box<dyn Fn(Namespace) -> Namespace> {
fn fill_env_prefix(prefix: String) -> Box<dyn Fn(Namespace) -> Namespace> {
Box::new(move |mut ns| {
let env_prefix = match &ns.env_prefix {
None => {
let env_prefix = format!(
"{}{}_",
prefix,
ns.name.clone().to_string()
);
let env_prefix = format!("{}{}_", prefix, ns.name.clone().to_string());
ns.env_prefix = Some(env_prefix.clone());
env_prefix
}
Some(env_prefix) => {
env_prefix.clone()
}
Some(env_prefix) => env_prefix.clone(),
};
if !ns.namespaces.is_empty() {
ns.namespaces = ns.namespaces.into_iter()
ns.namespaces = ns
.namespaces
.into_iter()
.map(fill_env_prefix(ns.env_prefix.clone().unwrap()))
.collect()
}
if !ns.variables.is_empty() {
ns.variables = ns.variables.into_iter()
ns.variables = ns
.variables
.into_iter()
.map(|mut var| {
if var.env_name.is_none() {
var.env_name = Some(
format!("{}{}", env_prefix.clone(), &var.name.to_string())
.to_uppercase()
.to_uppercase(),
);
}
var
@ -84,17 +83,21 @@ fn parse_namespace_content(
Ok(())
}
fn parse_attribute(attr: Attribute, name: &'static str, var: &Option<String>) -> Result<Option<String>> {
fn parse_attribute(
attr: Attribute,
name: &'static str,
var: &Option<String>,
) -> Result<Option<String>> {
if var.is_some() {
let message = format!("You cannot use {} meta twice", &name);
return Err(Error::new_spanned(attr, message));
}
match attr.parse_meta()? {
Meta::NameValue(MetaNameValue { lit: Lit::Str(lit_str), .. }) => {
Ok(Some(lit_str.value()))
}
Meta::NameValue(MetaNameValue {
lit: Lit::Str(lit_str),
..
}) => Ok(Some(lit_str.value())),
_ => {
let message = format!("expected #[{} = \"...\"]", &name);
Err(Error::new_spanned(attr, message))
@ -102,7 +105,6 @@ fn parse_attribute(attr: Attribute, name: &'static str, var: &Option<String>) ->
}
}
impl Parse for RootNamespace {
fn parse(input: ParseStream) -> Result<Self> {
let mut name: Option<Ident> = None;
@ -114,15 +116,20 @@ impl Parse for RootNamespace {
if attr.path.is_ident("config") {
match attr.parse_meta()? {
Meta::List(MetaList { nested, .. }) => {
let message = format!("expected #[config(name = \"...\")] or #[config(unwrap)]");
let message =
format!("expected #[config(name = \"...\")] or #[config(unwrap)]");
match nested.first().unwrap() {
NestedMeta::Meta(Meta::NameValue(MetaNameValue { path, lit: Lit::Str(lit_str), .. })) => {
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
path,
lit: Lit::Str(lit_str),
..
})) => {
if path.is_ident("name") {
name = Some(Ident::new(&lit_str.value(), Span::call_site()));
} else {
Err(Error::new_spanned(attr, message))?;
}
},
}
NestedMeta::Meta(Meta::Path(path)) => {
if path.is_ident("unwrap") {
name = None;
@ -130,7 +137,7 @@ impl Parse for RootNamespace {
} else {
Err(Error::new_spanned(attr, message))?;
}
},
}
_ => {
Err(Error::new_spanned(attr, message))?;
}
@ -157,7 +164,8 @@ impl Parse for RootNamespace {
}
let prefix = String::new();
let namespaces = namespaces.into_iter()
let namespaces = namespaces
.into_iter()
.map(fill_env_prefix(prefix.clone()))
.collect();
@ -170,7 +178,6 @@ impl Parse for RootNamespace {
}
}
impl Parse for Namespace {
fn parse(input: ParseStream) -> Result<Self> {
let name: Ident = input.parse()?;
@ -195,7 +202,6 @@ impl Parse for Namespace {
}
}
impl Parse for Variable {
fn parse(input: ParseStream) -> Result<Self> {
let is_static = input.parse::<Token![static]>().ok().is_some();
@ -243,7 +249,9 @@ impl Parse for Variable {
}
concat_parts = Some(tmp_vec);
} else {
initial = input.parse::<FatArrow>().ok()
initial = input
.parse::<FatArrow>()
.ok()
.and_then(|_| input.parse::<Expr>().ok());
};

View File

@ -1,4 +1,4 @@
use criterion::{Criterion, criterion_main, criterion_group, Fun};
use criterion::{criterion_group, criterion_main, Criterion, Fun};
use std::env;
#[macro_use]
@ -6,18 +6,14 @@ extern crate lazy_static;
#[macro_use]
extern crate itconfig;
fn setup_env_var(key: &'static str, initial: String) {
env::set_var(key, initial);
}
fn source_get_env() -> u32 {
itconfig::get_env::<u32>("TEST").unwrap()
}
fn lazy_get_env() -> u32 {
lazy_static! {
static ref RES: u32 = source_get_env();
@ -26,14 +22,11 @@ fn lazy_get_env() -> u32 {
return *RES;
}
fn source_vs_lazy(c: &mut Criterion) {
setup_env_var("TEST", "1".to_string());
let source = Fun::new("source", |b, _| {
b.iter(move || {
assert_eq!(source_get_env(), 1)
})
b.iter(move || assert_eq!(source_get_env(), 1))
});
let lazy = Fun::new("lazy", |b, _| {
b.iter(move || {
@ -44,7 +37,6 @@ fn source_vs_lazy(c: &mut Criterion) {
c.bench_functions("get_env", vec![source, lazy], 0);
}
fn source_macro_vs_lazy_macro(c: &mut Criterion) {
config! {
TEST: &'static str,
@ -83,7 +75,6 @@ fn source_macro_vs_lazy_macro(c: &mut Criterion) {
c.bench_functions("macro", funcs, 0);
}
criterion_group! {
benches,
source_vs_lazy,

View File

@ -10,7 +10,6 @@ mod test_case_1 {
}
}
mod test_case_2 {
use std::env;
@ -28,7 +27,6 @@ mod test_case_2 {
}
}
mod test_case_3 {
itconfig::config! {
DEBUG: bool => true,
@ -104,7 +102,6 @@ mod test_case_6 {
}
}
mod test_case_7 {
use std::env;
@ -158,7 +155,6 @@ mod test_case_7 {
}
}
mod test_case_8 {
itconfig::config! {
#![config(name = "custom_config_name")]
@ -173,7 +169,6 @@ mod test_case_8 {
}
}
mod test_case_9 {
use std::env;
@ -217,7 +212,6 @@ mod test_case_10 {
}
}
mod test_case_11 {
itconfig::config! {
FIRST {
@ -238,7 +232,6 @@ mod test_case_11 {
}
}
mod test_case_12 {
use std::env;
@ -261,7 +254,6 @@ mod test_case_12 {
}
}
mod test_case_13 {
use std::env;
@ -285,7 +277,6 @@ mod test_case_13 {
}
}
mod test_case_14 {
use std::env;
@ -312,7 +303,6 @@ mod test_case_14 {
}
}
mod test_case_15 {
use std::env;
@ -323,7 +313,6 @@ mod test_case_15 {
DEFAULT_ENV_FLOAT: f64 => 40.9,
}
#[test]
fn setting_default_env_variable() {
config::init();
@ -335,7 +324,6 @@ mod test_case_15 {
}
}
mod test_case_16 {
use std::env;
@ -360,11 +348,13 @@ mod test_case_16 {
env::set_var("POSTGRES_DB", "test");
config::init();
assert_eq!(config::DATABASE_URL(), String::from("postgres://user:pass@localhost/test"));
assert_eq!(
config::DATABASE_URL(),
String::from("postgres://user:pass@localhost/test")
);
}
}
mod test_case_17 {
use std::env;
@ -376,17 +366,18 @@ mod test_case_17 {
),
}
#[test]
fn setting_default_concat_env_variable() {
env::set_var("SETTING_DEFAULT_CONCAT_ENV_VARIABLE", "custom");
config::init();
assert_eq!(env::var("DEFAULT_CONCAT_ENV"), Ok("string/custom".to_string()));
assert_eq!(
env::var("DEFAULT_CONCAT_ENV"),
Ok("string/custom".to_string())
);
}
}
mod test_case_18 {
itconfig::config! {
DATABASE_URL < (
@ -408,7 +399,6 @@ mod test_case_18 {
}
}
mod test_case_19 {
use std::env;
@ -425,7 +415,6 @@ mod test_case_19 {
),
}
#[test]
fn default_value_for_concatenate_env_parameter() {
config::init();
@ -436,7 +425,6 @@ mod test_case_19 {
}
}
mod test_case_20 {
use std::env;
use std::env::VarError;
@ -466,7 +454,6 @@ mod test_case_20 {
}
}
mod test_case_21 {
use std::env;
use std::env::VarError;
@ -486,7 +473,6 @@ mod test_case_21 {
}
}
#[test]
fn concatenated_environment_variable_in_namespace() {
config::init();
@ -498,7 +484,6 @@ mod test_case_21 {
}
}
mod test_case_22 {
itconfig::config! {
static STATIC_STR => "test",
@ -523,7 +508,6 @@ mod test_case_22 {
),
}
#[test]
fn static_variables() {
config::init();

View File

@ -1,6 +1,6 @@
use std::env;
use itconfig::*;
use itconfig::EnvError::*;
use itconfig::*;
use std::env;
#[test]
#[should_panic(expected = "Environment variable \"TEST_CASE_1\" is missing")]

View File

@ -1,6 +1,5 @@
use failure::Fail;
#[derive(Debug, Fail, PartialEq)]
pub enum EnvError {
#[fail(display = r#"Environment variable "{}" is missing"#, env_name)]

View File

@ -1,12 +1,10 @@
use std::ops::Deref;
#[doc(hidden)]
pub trait ToEnvString {
fn to_env_string(&self) -> EnvString;
}
#[doc(hidden)]
pub trait FromEnvString: Sized {
type Err;
@ -14,10 +12,9 @@ pub trait FromEnvString: Sized {
fn from_env_string(s: &EnvString) -> Result<Self, Self::Err>;
}
impl<T> ToEnvString for T
where
T: ToString
where
T: ToString,
{
#[inline]
fn to_env_string(&self) -> EnvString {
@ -25,7 +22,6 @@ impl<T> ToEnvString for T
}
}
#[doc(hidden)]
macro_rules! from_env_string_numbers_impl {
($($ty:ty => $feature:expr),+) => {
@ -60,7 +56,6 @@ from_env_string_numbers_impl![
f64 => "f64"
];
#[cfg(feature = "bool")]
impl FromEnvString for bool {
type Err = ();
@ -68,13 +63,11 @@ impl FromEnvString for bool {
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)
_ => Ok(false),
}
}
}
#[cfg(feature = "array")]
#[derive(Debug)]
pub enum ArrayEnvError {
@ -82,21 +75,17 @@ pub enum ArrayEnvError {
FailedToParse,
}
#[cfg(feature = "array")]
impl<T> FromEnvString for Vec<T>
where T: FromEnvString
where
T: FromEnvString,
{
type Err = ArrayEnvError;
fn from_env_string(s: &EnvString) -> Result<Self, Self::Err> {
serde_json::from_str::<Vec<isize>>(s.trim())
.map(|vec| {
vec.iter().map(|v| v.to_string()).collect::<Vec<String>>()
})
.or_else(|_| {
serde_json::from_str::<Vec<String>>(s.trim())
})
.map(|vec| vec.iter().map(|v| v.to_string()).collect::<Vec<String>>())
.or_else(|_| serde_json::from_str::<Vec<String>>(s.trim()))
.map_err(|_| ArrayEnvError::InvalidType)
.and_then(|vec| {
vec.iter()
@ -110,7 +99,6 @@ impl<T> FromEnvString for Vec<T>
}
}
impl FromEnvString for String {
type Err = ();
@ -119,7 +107,6 @@ impl FromEnvString for String {
}
}
impl FromEnvString for &'static str {
type Err = ();
@ -128,7 +115,6 @@ impl FromEnvString for &'static str {
}
}
#[doc(hidden)]
#[derive(Debug, PartialEq, Clone)]
pub struct EnvString(String);
@ -146,5 +132,3 @@ impl Deref for EnvString {
&self.0
}
}

View File

@ -1,6 +1,5 @@
use std::env;
use crate::prelude::*;
use std::env;
/// This function is similar as `get_env`, but it unwraps result with panic on error.
///
@ -10,13 +9,12 @@ use crate::prelude::*;
/// expected type
///
pub fn get_env_or_panic<T>(env_name: &str) -> T
where
T: FromEnvString
where
T: FromEnvString,
{
get_env(env_name).unwrap_or_else(make_panic)
}
/// Try to read environment variable and parse to expected type. You may to put to argument
/// any type with `FromEnvString` trait.
///
@ -38,15 +36,16 @@ pub fn get_env_or_panic<T>(env_name: &str) -> T
/// ```
///
pub fn get_env<T>(env_name: &str) -> Result<T, EnvError>
where
T: FromEnvString
where
T: FromEnvString,
{
get_env_or(env_name, |_| {
Err(EnvError::MissingVariable { env_name: env_name.to_string() })
Err(EnvError::MissingVariable {
env_name: env_name.to_string(),
})
})
}
/// This function is similar as `get_env_or_panic`, but you can pass default value for
/// environment variable with `ToEnvString` trait.
///
@ -69,15 +68,13 @@ pub fn get_env<T>(env_name: &str) -> Result<T, EnvError>
/// ```
///
pub fn get_env_or_default<T, D>(env_name: &str, default: D) -> T
where
T: FromEnvString,
D: ToEnvString,
where
T: FromEnvString,
D: ToEnvString,
{
get_env_or(env_name, |_| Ok(default.to_env_string()))
.unwrap_or_else(make_panic)
get_env_or(env_name, |_| Ok(default.to_env_string())).unwrap_or_else(make_panic)
}
/// This function is similar as `get_env_or_default`, but the default value will be set to environment
/// variable, if env variable is missed.
///
@ -103,45 +100,41 @@ pub fn get_env_or_default<T, D>(env_name: &str, default: D) -> T
/// ```
///
pub fn get_env_or_set_default<T, D>(env_name: &str, default: D) -> T
where
T: FromEnvString,
D: ToEnvString,
where
T: FromEnvString,
D: ToEnvString,
{
get_env_or(env_name, |_| {
let val = default.to_env_string();
env::set_var(env_name, val.as_str());
Ok(val)
}).unwrap_or_else(make_panic)
})
.unwrap_or_else(make_panic)
}
/// This function returns env variable as `EnvString` structure. You can pass callback for custom
/// default expression. Callback should return `EnvString` value or `EnvError`
pub fn get_env_or<T, F>(env_name: &str, cb: F) -> Result<T, EnvError>
where
T: FromEnvString,
F: FnOnce(env::VarError) -> Result<EnvString, EnvError>
where
T: FromEnvString,
F: FnOnce(env::VarError) -> Result<EnvString, EnvError>,
{
env::var(env_name)
.map(|s| s.to_env_string())
.or_else(cb)
.and_then(|env_str| {
parse_env_variable(env_name, env_str)
})
.and_then(|env_str| parse_env_variable(env_name, env_str))
}
#[doc(hidden)]
fn parse_env_variable<T>(env_name: &str, env_str: EnvString) -> Result<T, EnvError>
where
T: FromEnvString
where
T: FromEnvString,
{
env_str
.parse::<T>()
.map_err(|_| EnvError::FailedToParse { env_name: env_name.to_string() })
env_str.parse::<T>().map_err(|_| EnvError::FailedToParse {
env_name: env_name.to_string(),
})
}
#[doc(hidden)]
fn make_panic<T>(e: EnvError) -> T {
panic!("{}", e)

View File

@ -134,14 +134,13 @@
//! * **bool** - impl EnvString for `bool` type
//!
// Rustc lints.
#![deny(
missing_debug_implementations,
unsafe_code,
unstable_features,
unused_imports,
unused_qualifications,
unused_qualifications
)]
/////////////////////////////////////////////////////////////////////////////
@ -150,19 +149,18 @@
extern crate failure;
mod enverr;
mod getenv;
pub mod envstr;
mod getenv;
pub use self::getenv::*;
pub use self::enverr::*;
pub use self::getenv::*;
pub mod prelude {
pub use crate::envstr::*;
pub use crate::enverr::*;
pub use crate::envstr::*;
}
#[cfg(feature = "macro")]
extern crate itconfig_macro;
#[cfg(feature = "macro")]
pub use itconfig_macro::*;
pub use itconfig_macro::*;