From b223bc811ef7563e6749d27f8cb8bfd9e2384a7f Mon Sep 17 00:00:00 2001 From: Dmitriy Pleshevskiy Date: Sun, 24 Jul 2022 15:50:34 +0300 Subject: [PATCH] chore: remove benches and old config macro --- Cargo.lock | 18 +-- Cargo.toml | 8 +- benches/main_benches.rs | 84 ---------- enve_mod/Cargo.toml | 29 ---- enve_mod/src/ast.rs | 29 ---- enve_mod/src/expand.rs | 186 ---------------------- enve_mod/src/lib.rs | 342 ---------------------------------------- enve_mod/src/parse.rs | 284 --------------------------------- enve_mod/src/utils.rs | 88 ----------- src/lib.rs | 5 - 10 files changed, 6 insertions(+), 1067 deletions(-) delete mode 100644 benches/main_benches.rs delete mode 100644 enve_mod/Cargo.toml delete mode 100644 enve_mod/src/ast.rs delete mode 100644 enve_mod/src/expand.rs delete mode 100644 enve_mod/src/lib.rs delete mode 100644 enve_mod/src/parse.rs delete mode 100644 enve_mod/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index ac6a9ae..4c96d5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "atty" version = "0.2.14" @@ -178,25 +180,15 @@ name = "enve" version = "1.1.1" dependencies = [ "criterion", - "enve_mod", "estring", "lazy_static", ] -[[package]] -name = "enve_mod" -version = "1.1.1" -dependencies = [ - "enve", - "lazy_static", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "estring" -version = "0.1.0" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ea7e904ef7cb950eee02f9332b6a5c24c33bebeca6c027651b04f6c20658d9" [[package]] name = "half" diff --git a/Cargo.toml b/Cargo.toml index c4ca931..c2f27ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,5 @@ [workspace] -members = [ - "estring", - "enve_mod", -] +members = [] [package] name = "enve" @@ -26,11 +23,8 @@ number = ["estring/number"] bool = ["estring/bool"] vec = ["estring/vec"] -macro = ["enve_mod"] - [dependencies] estring = "0.1" -enve_mod = { version = "1.1", path = "./enve_mod", optional = true } [dev-dependencies] lazy_static = "1.4.0" diff --git a/benches/main_benches.rs b/benches/main_benches.rs deleted file mode 100644 index 3142d78..0000000 --- a/benches/main_benches.rs +++ /dev/null @@ -1,84 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion, Fun}; -use std::env; - -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate enve; - -fn setup_env_var(key: &'static str, initial: String) { - env::set_var(key, initial); -} - -fn source_get_env() -> u32 { - enve::get::("TEST").unwrap() -} - -fn lazy_get_env() -> u32 { - lazy_static! { - static ref RES: u32 = source_get_env(); - }; - - 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)) - }); - let lazy = Fun::new("lazy", |b, _| { - b.iter(move || { - assert_eq!(lazy_get_env(), 1); - }) - }); - - c.bench_functions("get_env", vec![source, lazy], 0); -} - -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!(config::TEST(), "test"); - }) - }); - let lazy = Fun::new("lazy", |b, _| { - b.iter(move || { - assert_eq!(config::LAZY_TEST(), "test"); - }) - }); - let source_with_default = Fun::new("source_with_default", |b, _| { - b.iter(move || { - assert_eq!(config::TEST_WITH_DEFAULT(), "default"); - }) - }); - let lazy_with_default = Fun::new("lazy_with_default", |b, _| { - b.iter(move || { - assert_eq!(config::LAZY_TEST_WITH_DEFAULT(), "default"); - }) - }); - - let funcs = vec![source, lazy, source_with_default, lazy_with_default]; - - c.bench_functions("macro", funcs, 0); -} - -criterion_group! { - benches, - source_vs_lazy, - source_macro_vs_lazy_macro, -} - -criterion_main!(benches); diff --git a/enve_mod/Cargo.toml b/enve_mod/Cargo.toml deleted file mode 100644 index bb3b161..0000000 --- a/enve_mod/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "enve_mod" -version = "1.1.1" -authors = ["Dmitriy Pleshevskiy "] -description = "Easy build a configs from environment variables and use it in globally." -categories = ["config", "web-programming"] -keywords = ["config", "env", "configuration", "environment", "macro"] -edition = "2018" -license = "MIT" -repository = "https://github.com/pleshevskiy/enve" -homepage = "https://github.com/pleshevskiy/enve" -documentation = "https://docs.rs/enve" -readme = "../README.md" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[lib] -proc-macro = true - -[dependencies] -syn = "1.0.60" -quote = "1.0.9" -proc-macro2 = "1.0.24" - -[dev-dependencies] -enve = { path = ".." } -lazy_static = "1.4.0" - -[badges] -maintenance = { status = "actively-developed" } diff --git a/enve_mod/src/ast.rs b/enve_mod/src/ast.rs deleted file mode 100644 index e3ea887..0000000 --- a/enve_mod/src/ast.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::utils::SupportedBox; -use proc_macro2::TokenStream as TokenStream2; -use syn::{Attribute, Expr, Ident, Type}; - -pub(crate) struct RootNamespace { - pub name: Option, - pub variables: Vec, - pub namespaces: Vec, - pub meta: Vec, -} - -pub(crate) struct Namespace { - pub name: Ident, - pub variables: Vec, - pub namespaces: Vec, - pub env_prefix: Option, - pub meta: Vec, -} - -pub(crate) struct Variable { - pub is_static: bool, - pub name: Ident, - pub ty: Type, - pub initial: Option, - pub concat_parts: Option>, - pub env_name: Option, - pub meta: Vec, - pub supported_box: Option, -} diff --git a/enve_mod/src/expand.rs b/enve_mod/src/expand.rs deleted file mode 100644 index 6894aac..0000000 --- a/enve_mod/src/expand.rs +++ /dev/null @@ -1,186 +0,0 @@ -use crate::ast::*; -use crate::utils::{vec_to_token_stream_2, SupportedBox}; -use proc_macro2::TokenStream as TokenStream2; -use quote::{quote, ToTokens, TokenStreamExt}; - -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() - .map(|var| { - let name = &var.name; - let var_meta = vec_to_token_stream_2(&var.meta); - - quote!( - #(#var_meta)* - #name(); - ) - }) - .collect::>(); - let init_namespaces = self - .namespaces - .iter() - .map(|ns| { - let name = &ns.name; - let ns_meta = vec_to_token_stream_2(&ns.meta); - - quote!( - #(#ns_meta)* - #name::init(); - ) - }) - .collect::>(); - - let inner_meta: Vec = if name.is_none() { - vec![] - } 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)* - - #(#namespaces)* - - #(#variables)* - - pub fn init() { - #(#init_variables)* - #(#init_namespaces)* - } - }; - - 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; - let variables = vec_to_token_stream_2(&self.variables); - let namespaces = vec_to_token_stream_2(&self.namespaces); - let meta = vec_to_token_stream_2(&self.meta); - - let init_variables = self - .variables - .iter() - .map(|var| { - let name = &var.name; - let var_meta = vec_to_token_stream_2(&var.meta); - - quote!( - #(#var_meta)* - #name(); - ) - }) - .collect::>(); - let init_namespaces = self - .namespaces - .iter() - .map(|ns| { - let name = &ns.name; - let ns_meta = vec_to_token_stream_2(&ns.meta); - - quote!( - #(#ns_meta)* - #name::init(); - ) - }) - .collect::>(); - - tokens.append_all(quote!( - #(#meta)* - pub mod #name { - #(#namespaces)* - - #(#variables)* - - pub fn init() { - #(#init_variables)* - #(#init_namespaces)* - } - } - )) - } -} - -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() - .unwrap_or_else(|| name.to_string().to_uppercase()); - let meta = vec_to_token_stream_2(&self.meta); - - let get_variable: TokenStream2 = if self.concat_parts.is_some() { - let concat_parts = self.concat_parts.as_ref().unwrap(); - quote! {{ - let value_parts: Vec = vec!(#(#concat_parts),*); - let value = value_parts.join(""); - ::std::env::set_var(#env_name, value.as_str()); - value - }} - } else if let Some(initial) = &self.initial { - match self.supported_box.clone() { - Some(SupportedBox::Vec(params)) => { - let sep = ¶ms.sep(); - quote!(::itconfig::get_vec_env_or_set_default(#env_name, #sep, #initial)) - } - _ => quote!(::itconfig::get_env_or_set_default(#env_name, #initial)), - } - } else { - match self.supported_box.clone() { - Some(SupportedBox::Option) => { - quote!(::itconfig::maybe_get_env(#env_name)) - } - Some(SupportedBox::OptionVec(params)) => { - let sep = ¶ms.sep(); - quote!(::itconfig::maybe_get_vec_env(#env_name, #sep)) - } - Some(SupportedBox::Vec(params)) => { - let sep = ¶ms.sep(); - quote!(::itconfig::get_vec_env_or_panic(#env_name, #sep)) - } - None => { - quote!(::itconfig::get_env_or_panic(#env_name)) - } - } - }; - - if self.is_static { - tokens.append_all(quote!( - #(#meta)* - pub fn #name() -> #ty { - ::lazy_static::lazy_static! { - static ref #name: #ty = #get_variable; - } - - (*#name).clone() - } - )); - } else { - tokens.append_all(quote!( - #(#meta)* - pub fn #name() -> #ty { - #get_variable - } - )); - } - } -} diff --git a/enve_mod/src/lib.rs b/enve_mod/src/lib.rs deleted file mode 100644 index edb51a8..0000000 --- a/enve_mod/src/lib.rs +++ /dev/null @@ -1,342 +0,0 @@ -#![recursion_limit = "256"] -#![deny(clippy::all)] -#![forbid(unsafe_code)] -#![forbid(non_ascii_idents)] - -mod ast; -mod expand; -mod parse; -mod utils; - -extern crate proc_macro; -extern crate proc_macro2; - -use self::proc_macro::TokenStream; -use ast::RootNamespace; -use quote::ToTokens; -use syn::parse_macro_input; - -/// ### _This API requires the following crate features to be activated: `macro`_ -/// -/// 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 -/// # use itconfig::config; -/// # use std::env; -/// config! { -/// DATABASE_URL: String, -/// } -/// -/// # fn main() { -/// # env::set_var("DATABASE_URL", "postgres://u:p@localhost:5432/db"); -/// # config::init(); -/// # } -/// ``` -/// -/// Config with default value -/// -/// ```rust -/// # use itconfig::config; -/// # use std::env; -/// config! { -/// DATABASE_URL: String, -/// HOST: String => "127.0.0.1", -/// } -/// # fn main() { -/// # env::set_var("DATABASE_URL", "postgres://u:p@localhost:5432/db"); -/// # config::init(); -/// # } -/// ``` -/// -/// By default itconfig lib creates module with 'config' name. But you can use simple meta instruction -/// if you want to rename module. In the example below we renamed module to 'configuration' -/// -/// ```rust -/// # use itconfig::config; -/// # use std::env; -/// config! { -/// #![config(name = "configuration")] -/// -/// DEBUG: bool, -/// } -/// -/// fn main() { -/// env::set_var("DEBUG", "t"); -/// -/// configuration::init(); -/// assert_eq!(configuration::DEBUG(), true); -/// } -/// ``` -/// -/// You also unwrap first config module -/// -/// ```rust -/// # use itconfig::config; -/// # use std::env; -/// -/// config! { -/// #![config(unwrap)] -/// -/// DEBUG: bool, -/// } -/// -/// fn main() { -/// env::set_var("DEBUG", "t"); -/// -/// init(); -/// assert_eq!(DEBUG(), true); -/// } -/// ``` -/// -/// -/// Namespaces -/// ---------- -/// -/// You can use namespaces for env variables -/// -/// ```rust -/// # use itconfig::config; -/// # use std::env; -/// -/// config! { -/// DEBUG: bool, -/// DATABASE { -/// USERNAME: String, -/// PASSWORD: String, -/// HOST: String, -/// } -/// } -/// fn main() { -/// env::set_var("DEBUG", "t"); -/// env::set_var("DATABASE_USERNAME", "user"); -/// env::set_var("DATABASE_PASSWORD", "pass"); -/// env::set_var("DATABASE_HOST", "localhost"); -/// -/// config::init(); -/// } -/// ``` -/// -/// Now you can use nested structure in namespaces without limits :) -/// -/// ```rust -/// # use itconfig::config; -/// config! { -/// FIRST { -/// SECOND { -/// THIRD { -/// FOO: bool => true, -/// } -/// } -/// } -/// } -/// # fn main() { config::init () } -/// ``` -/// -/// Namespaces supports custom meta -/// -/// ```rust -/// # use itconfig::config; -/// config! { -/// #[cfg(feature = "first")] -/// FIRST { -/// #[cfg(feature = "second")] -/// SECOND { -/// #[cfg(feature = "third")] -/// THIRD { -/// FOO: bool => true, -/// } -/// } -/// } -/// } -/// # fn main() { config::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 -/// # use itconfig::config; -/// # use std::env; -/// -/// config! { -/// #[env_name = "MY_CUSTOM_NAME"] -/// PER_PAGE: i32, -/// -/// APP { -/// #[env_name = "MY_CUSTOM_NAME"] -/// RECIPES_PER_PAGE: i32, -/// } -/// } -/// -/// fn main() { -/// env::set_var("MY_CUSTOM_NAME", "95"); -/// -/// config::init(); -/// assert_eq!(config::PER_PAGE(), 95); -/// assert_eq!(config::APP::RECIPES_PER_PAGE(), 95); -/// } -/// ``` -/// -/// Also you can add custom meta for each variable. For example feature configurations. -/// -/// ```rust -/// # use itconfig::config; -/// 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 -/// # use itconfig::config; -/// # use std::env; -/// config! { -/// DATABASE_URL < ( -/// "postgres://", -/// POSTGRES_USERNAME, -/// ":", -/// POSTGRES_PASSWORD, -/// "@", -/// POSTGRES_HOST => "localhost:5432", -/// "/", -/// POSTGRES_DB => "test", -/// ), -/// } -/// -/// fn main() { -/// env::set_var("POSTGRES_USERNAME", "user"); -/// env::set_var("POSTGRES_PASSWORD", "pass"); -/// -/// config::init(); -/// assert_eq!(config::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 -/// # use itconfig::config; -/// 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", -/// ), -/// } -/// } -/// # fn main() { config::init () } -/// ``` -/// -/// Static -/// ------ -/// -/// Starting with 0.11 version you can use lazy static for improve speed of variable. This is very -/// useful, if you use variable more than once. -/// -/// ```rust -/// # use itconfig::config; -/// # use std::env; -/// config! { -/// static APP_BASE_URL => "/api", -/// } -/// -/// fn main () { -/// env::set_var("APP_BASE_URL", "/api/v1"); -/// -/// config::init(); -/// assert_eq!(config::APP_BASE_URL(), "/api/v1"); -/// } -/// ``` -/// -/// You also can use static with concat variables -/// -/// ```rust -/// # use itconfig::config; -/// config! { -/// static CONNECTION_STRING < ( -/// "postgres://", -/// NOT_DEFINED_PG_USERNAME => "user", -/// ":", -/// NOT_DEFINED_PG_PASSWORD => "pass", -/// "@", -/// NOT_DEFINED_PG_HOST => "localhost:5432", -/// "/", -/// NOT_DEFINED_PG_DB => "test", -/// ), -/// } -/// -/// fn main () { -/// config::init(); -/// assert_eq!(config::CONNECTION_STRING(), "postgres://user:pass@localhost:5432/test".to_string()); -/// } -/// ``` -/// -/// -/// --- -/// -/// 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 -/// # use itconfig::config; -/// // use dotenv::dotenv; -/// -/// config! { -/// DEBUG: bool => true, -/// HOST: String => "127.0.0.1", -/// } -/// -/// fn main () { -/// // dotenv().ok(); -/// config::init(); -/// assert_eq!(config::HOST(), String::from("127.0.0.1")); -/// } -/// ``` -/// -#[proc_macro] -pub fn config(input: TokenStream) -> TokenStream { - let namespace = parse_macro_input!(input as RootNamespace); - namespace.into_token_stream().into() -} diff --git a/enve_mod/src/parse.rs b/enve_mod/src/parse.rs deleted file mode 100644 index 241e9da..0000000 --- a/enve_mod/src/parse.rs +++ /dev/null @@ -1,284 +0,0 @@ -use crate::ast::*; -use crate::utils::{maybe_supported_box, SupportedBox, VecBoxParams}; -use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; -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 Namespace> { - Box::new(move |mut ns| { - let env_prefix = match &ns.env_prefix { - None => { - let env_prefix = format!("{}{}_", prefix, ns.name.clone()); - ns.env_prefix = Some(env_prefix.clone()); - env_prefix - } - Some(env_prefix) => env_prefix.clone(), - }; - - if !ns.namespaces.is_empty() { - 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() - .map(|mut var| { - if var.env_name.is_none() { - var.env_name = Some( - format!("{}{}", env_prefix.clone(), &var.name.to_string()) - .to_uppercase(), - ); - } - var - }) - .collect() - } - - ns - }) -} - -fn parse_namespace_content( - input: &ParseBuffer, - variables: &mut Vec, - namespaces: &mut Vec, -) -> Result<()> { - let attributes: Vec = input.call(Attribute::parse_outer)?; - if input.peek2(Brace) { - let mut namespace: Namespace = input.parse()?; - - for attr in attributes { - if attr.path.is_ident("env_prefix") { - let env_prefix = parse_attribute(attr, "env_prefix", &namespace.env_prefix)?; - namespace.env_prefix = Some(env_prefix); - } else { - namespace.meta.push(attr); - } - } - - namespaces.push(namespace); - } else { - let mut variable: Variable = input.parse()?; - - for attr in attributes { - if attr.path.is_ident("env_name") { - let env_name = parse_attribute(attr, "env_name", &variable.env_name)?; - variable.env_name = Some(env_name); - } else { - match variable.supported_box { - Some(SupportedBox::Vec(params)) if attr.path.is_ident("sep") => { - let sep = parse_attribute(attr, "sep", ¶ms.sep_opt())?; - variable.supported_box = - Some(SupportedBox::Vec(VecBoxParams::new(Some(sep)))); - } - _ => variable.meta.push(attr), - } - } - } - - variables.push(variable); - } - - Ok(()) -} - -fn parse_attribute(attr: Attribute, name: &'static str, var: &Option) -> Result { - 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(lit_str.value()), - _ => { - let message = format!("expected #[{} = \"...\"]", &name); - Err(Error::new_spanned(attr, message)) - } - } -} - -impl Parse for RootNamespace { - fn parse(input: ParseStream) -> Result { - let mut name: Option = None; - let mut with_module = true; - let mut meta: Vec = vec![]; - - let attributes: Vec = input.call(Attribute::parse_inner)?; - for attr in attributes { - if attr.path.is_ident("config") { - match attr.parse_meta()? { - Meta::List(MetaList { nested, .. }) => { - let message = - "expected #[config(name = \"...\")] or #[config(unwrap)]".to_string(); - match nested.first().unwrap() { - 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 { - return Err(Error::new_spanned(attr, message)); - } - } - NestedMeta::Meta(Meta::Path(path)) => { - if path.is_ident("unwrap") { - name = None; - with_module = false; - } else { - return Err(Error::new_spanned(attr, message)); - } - } - _ => { - return Err(Error::new_spanned(attr, message)); - } - } - } - _ => { - let message = "expected #[config(...)]".to_string(); - return Err(Error::new_spanned(attr, message)); - } - } - } else { - meta.push(attr); - } - } - - if with_module && name.is_none() { - name = Some(Ident::new("config", Span::call_site())); - } - - let mut variables: Vec = vec![]; - let mut namespaces: Vec = vec![]; - while !input.is_empty() { - parse_namespace_content(input, &mut variables, &mut namespaces)?; - } - - let prefix = String::new(); - let namespaces = namespaces - .into_iter() - .map(fill_env_prefix(prefix)) - .collect(); - - Ok(RootNamespace { - name, - variables, - namespaces, - meta, - }) - } -} - -impl Parse for Namespace { - fn parse(input: ParseStream) -> Result { - let name: Ident = input.parse()?; - let mut variables: Vec = vec![]; - let mut namespaces: Vec = vec![]; - - let content; - braced!(content in input); - while !content.is_empty() { - parse_namespace_content(&content, &mut variables, &mut namespaces)?; - } - - input.parse::().ok(); - - Ok(Namespace { - name, - variables, - namespaces, - env_prefix: None, - meta: vec![], - }) - } -} - -impl Parse for Variable { - fn parse(input: ParseStream) -> Result { - let is_static = input.parse::().ok().is_some(); - let name: Ident = input.parse()?; - - let is_concat = input.peek(Lt); - let mut concat_parts = None; - let mut initial = None; - - let ty: Type = if is_concat { - parse_str("String")? - } else if input.peek(Colon) { - input.parse::()?; - input.parse()? - } else { - parse_str("&'static str")? - }; - - let supported_box = maybe_supported_box(&ty); - - if is_concat { - input.parse::()?; - - let content; - parenthesized!(content in input); - - let mut tmp_vec: Vec = vec![]; - while !content.is_empty() { - if content.peek(Ident::peek_any) { - let concat_var: Variable = content.parse()?; - let name = &concat_var.name; - let env_name = &concat_var - .env_name - .clone() - .unwrap_or_else(|| name.to_string()); - - let get_variable = if concat_var.initial.is_some() { - let initial = concat_var.initial.as_ref().unwrap(); - quote!(::itconfig::get_env_or_set_default(#env_name, #initial)) - } else { - quote!(::itconfig::get_env_or_panic(#env_name)) - }; - - tmp_vec.push(get_variable); - } else { - let part: Lit = content.parse()?; - tmp_vec.push(quote!(#part.to_string())); - } - - content.parse::().ok(); - } - - concat_parts = Some(tmp_vec); - } else { - initial = input - .parse::() - .ok() - .and_then(|_| input.parse::().ok()); - }; - - input.parse::().ok(); - - Ok(Variable { - supported_box, - is_static, - name, - ty, - initial, - concat_parts, - env_name: None, - meta: vec![], - }) - } -} diff --git a/enve_mod/src/utils.rs b/enve_mod/src/utils.rs deleted file mode 100644 index fe62e95..0000000 --- a/enve_mod/src/utils.rs +++ /dev/null @@ -1,88 +0,0 @@ -use proc_macro2::TokenStream as TokenStream2; -use quote::ToTokens; -use syn::{GenericArgument, Path, PathArguments, Type}; - -const OPTION_PATH_IDENTS: &[&str] = &["Option|", "std|option|Option|", "core|option|Option|"]; -const VEC_PATH_IDENTS: &[&str] = &["Vec|", "std|vec|Vec|"]; - -#[derive(Debug, Clone, Default)] -pub(crate) struct VecBoxParams(Option); - -impl VecBoxParams { - #[inline] - pub(crate) fn new(sep: Option) -> Self { - VecBoxParams(sep) - } - - #[inline] - pub(crate) fn sep_opt(&self) -> Option { - self.0.clone() - } - - #[inline] - pub(crate) fn sep(&self) -> String { - self.0.clone().unwrap_or_else(|| String::from(",")) - } -} - -#[derive(Debug, Clone)] -pub(crate) enum SupportedBox { - Vec(VecBoxParams), - Option, - OptionVec(VecBoxParams), -} - -pub(crate) fn vec_to_token_stream_2(input: &[T]) -> Vec -where - T: ToTokens, -{ - input.iter().map(|ns| ns.into_token_stream()).collect() -} - -fn path_ident(path: &Path) -> String { - path.segments - .iter() - .into_iter() - .fold(String::with_capacity(250), |mut acc, v| { - acc.push_str(&v.ident.to_string()); - acc.push('|'); - acc - }) -} - -fn is_option_path_ident(path_ident: &str) -> bool { - OPTION_PATH_IDENTS.iter().any(|s| path_ident == *s) -} - -fn is_vec_path_ident(path_ident: &str) -> bool { - VEC_PATH_IDENTS.iter().any(|s| path_ident == *s) -} - -pub(crate) fn maybe_supported_box(ty: &Type) -> Option { - match ty { - Type::Path(ty_path) if ty_path.qself.is_none() => { - let ty_path_ident = path_ident(&ty_path.path); - if is_option_path_ident(&ty_path_ident) { - if let PathArguments::AngleBracketed(params) = - &ty_path.path.segments.iter().last().unwrap().arguments - { - if let Some(GenericArgument::Type(Type::Path(inner_ty_path))) = - params.args.first() - { - let ty_path_ident = path_ident(&inner_ty_path.path); - if is_vec_path_ident(&ty_path_ident) { - return Some(SupportedBox::OptionVec(Default::default())); - } - } - } - - Some(SupportedBox::Option) - } else if is_vec_path_ident(&ty_path_ident) { - Some(SupportedBox::Vec(Default::default())) - } else { - None - } - } - _ => None, - } -} diff --git a/src/lib.rs b/src/lib.rs index ebf8312..e82bb54 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -156,8 +156,3 @@ pub mod estr; pub use self::core::*; pub use self::core::{get, get_or_set_default, sget, sset}; pub use self::error::Error; - -#[cfg(feature = "macro")] -extern crate enve_mod; -#[cfg(feature = "macro")] -pub use enve_mod::*;