chore: remove benches and old config macro

This commit is contained in:
Dmitriy Pleshevskiy 2022-07-24 15:50:34 +03:00
parent 3686486847
commit b223bc811e
Signed by: pleshevskiy
GPG key ID: 1B59187B161C0215
10 changed files with 6 additions and 1067 deletions

18
Cargo.lock generated
View file

@ -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"

View file

@ -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"

View file

@ -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::<u32>("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);

View file

@ -1,29 +0,0 @@
[package]
name = "enve_mod"
version = "1.1.1"
authors = ["Dmitriy Pleshevskiy <dmitriy@ideascup.me>"]
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" }

View file

@ -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<Ident>,
pub variables: Vec<Variable>,
pub namespaces: Vec<Namespace>,
pub meta: Vec<Attribute>,
}
pub(crate) struct Namespace {
pub name: Ident,
pub variables: Vec<Variable>,
pub namespaces: Vec<Namespace>,
pub env_prefix: Option<String>,
pub meta: Vec<Attribute>,
}
pub(crate) struct Variable {
pub is_static: bool,
pub name: Ident,
pub ty: Type,
pub initial: Option<Expr>,
pub concat_parts: Option<Vec<TokenStream2>>,
pub env_name: Option<String>,
pub meta: Vec<Attribute>,
pub supported_box: Option<SupportedBox>,
}

View file

@ -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::<Vec<TokenStream2>>();
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::<Vec<TokenStream2>>();
let inner_meta: Vec<TokenStream2> = 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::<Vec<TokenStream2>>();
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::<Vec<TokenStream2>>();
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<String> = 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 = &params.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 = &params.sep();
quote!(::itconfig::maybe_get_vec_env(#env_name, #sep))
}
Some(SupportedBox::Vec(params)) => {
let sep = &params.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
}
));
}
}
}

View file

@ -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()
}

View file

@ -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<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());
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<Variable>,
namespaces: &mut Vec<Namespace>,
) -> Result<()> {
let attributes: Vec<Attribute> = 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", &params.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<String>) -> Result<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(lit_str.value()),
_ => {
let message = format!("expected #[{} = \"...\"]", &name);
Err(Error::new_spanned(attr, message))
}
}
}
impl Parse for RootNamespace {
fn parse(input: ParseStream) -> Result<Self> {
let mut name: Option<Ident> = None;
let mut with_module = true;
let mut meta: Vec<Attribute> = vec![];
let attributes: Vec<Attribute> = 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<Variable> = vec![];
let mut namespaces: Vec<Namespace> = 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<Self> {
let name: Ident = input.parse()?;
let mut variables: Vec<Variable> = vec![];
let mut namespaces: Vec<Namespace> = vec![];
let content;
braced!(content in input);
while !content.is_empty() {
parse_namespace_content(&content, &mut variables, &mut namespaces)?;
}
input.parse::<Comma>().ok();
Ok(Namespace {
name,
variables,
namespaces,
env_prefix: None,
meta: vec![],
})
}
}
impl Parse for Variable {
fn parse(input: ParseStream) -> Result<Self> {
let is_static = input.parse::<Token![static]>().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::<Colon>()?;
input.parse()?
} else {
parse_str("&'static str")?
};
let supported_box = maybe_supported_box(&ty);
if is_concat {
input.parse::<Lt>()?;
let content;
parenthesized!(content in input);
let mut tmp_vec: Vec<TokenStream2> = 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::<Comma>().ok();
}
concat_parts = Some(tmp_vec);
} else {
initial = input
.parse::<FatArrow>()
.ok()
.and_then(|_| input.parse::<Expr>().ok());
};
input.parse::<Comma>().ok();
Ok(Variable {
supported_box,
is_static,
name,
ty,
initial,
concat_parts,
env_name: None,
meta: vec![],
})
}
}

View file

@ -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<String>);
impl VecBoxParams {
#[inline]
pub(crate) fn new(sep: Option<String>) -> Self {
VecBoxParams(sep)
}
#[inline]
pub(crate) fn sep_opt(&self) -> Option<String> {
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<T>(input: &[T]) -> Vec<TokenStream2>
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<SupportedBox> {
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,
}
}

View file

@ -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::*;