mirror of
https://github.com/Steffo99/micronfig.git
synced 2024-12-23 04:24:18 +00:00
Compare commits
No commits in common. "7146c97f28f693a224be4c7c45ae47964250f9cf" and "ffa218b39b4a6fe43f0d8b8edeb8e9ab4ada41f4" have entirely different histories.
7146c97f28
...
ffa218b39b
21 changed files with 125 additions and 183 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="DiscordProjectSettings">
|
<component name="DiscordProjectSettings">
|
||||||
<option name="show" value="ASK" />
|
<option name="show" value="ASK" />
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/micronfig.iml" filepath="$PROJECT_DIR$/micronfig.iml" />
|
<module fileurl="file://$PROJECT_DIR$/_workspace.iml" filepath="$PROJECT_DIR$/_workspace.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/micronfig/micronfig.iml" filepath="$PROJECT_DIR$/micronfig/micronfig.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/micronfig_macros/micronfig_macros.iml" filepath="$PROJECT_DIR$/micronfig_macros/micronfig_macros.iml" />
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -1,19 +0,0 @@
|
||||||
<component name="ProjectRunConfigurationManager">
|
|
||||||
<configuration default="false" name="Doc" type="CargoCommandRunConfiguration" factoryName="Cargo Command" nameIsGenerated="true">
|
|
||||||
<option name="command" value="doc --open" />
|
|
||||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
|
||||||
<envs />
|
|
||||||
<option name="emulateTerminal" value="true" />
|
|
||||||
<option name="channel" value="DEFAULT" />
|
|
||||||
<option name="requiredFeatures" value="true" />
|
|
||||||
<option name="allFeatures" value="false" />
|
|
||||||
<option name="withSudo" value="false" />
|
|
||||||
<option name="buildTarget" value="REMOTE" />
|
|
||||||
<option name="backtrace" value="SHORT" />
|
|
||||||
<option name="isRedirectInput" value="false" />
|
|
||||||
<option name="redirectInputPath" value="" />
|
|
||||||
<method v="2">
|
|
||||||
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
|
||||||
</method>
|
|
||||||
</configuration>
|
|
||||||
</component>
|
|
|
@ -1,20 +0,0 @@
|
||||||
<component name="ProjectRunConfigurationManager">
|
|
||||||
<configuration default="false" name="Test" type="CargoCommandRunConfiguration" factoryName="Cargo Command" nameIsGenerated="true">
|
|
||||||
<option name="buildProfileId" value="test" />
|
|
||||||
<option name="command" value="test -- --test-threads=1" />
|
|
||||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
|
||||||
<envs />
|
|
||||||
<option name="emulateTerminal" value="true" />
|
|
||||||
<option name="channel" value="DEFAULT" />
|
|
||||||
<option name="requiredFeatures" value="true" />
|
|
||||||
<option name="allFeatures" value="false" />
|
|
||||||
<option name="withSudo" value="false" />
|
|
||||||
<option name="buildTarget" value="REMOTE" />
|
|
||||||
<option name="backtrace" value="FULL" />
|
|
||||||
<option name="isRedirectInput" value="false" />
|
|
||||||
<option name="redirectInputPath" value="" />
|
|
||||||
<method v="2">
|
|
||||||
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
|
||||||
</method>
|
|
||||||
</configuration>
|
|
||||||
</component>
|
|
Binary file not shown.
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 6.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 159 KiB |
|
@ -1,26 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<svg height="100%" id="emblematic-background" version="1.1" viewBox="0 0 512 512" width="100%" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<defs>
|
|
||||||
<linearGradient gradientUnits="userSpaceOnUse" id="background" x2="512" y1="512">
|
|
||||||
<stop offset="0" stop-color="#051436"/>
|
|
||||||
<stop offset=".75" stop-color="#001553"/>
|
|
||||||
<stop offset="1" stop-color="#010a4e"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect fill="url(#background)" height="512" width="512"/>
|
|
||||||
</svg>
|
|
||||||
<svg height="63%" id="emblematic-icon" preserveAspectRatio="xMidYMid meet" viewBox="0 0 512 512" width="63%" x="94.72" xmlns="http://www.w3.org/2000/svg" y="94.72">
|
|
||||||
<defs>
|
|
||||||
<filter color-interpolation-filters="sRGB" id="emblematic-filter">
|
|
||||||
<feFlood flood-color="rgb(1,8,40)" in="SourceGraphic" result="flood"/>
|
|
||||||
<feGaussianBlur in="SourceGraphic" result="blur" stdDeviation="10"/>
|
|
||||||
<feOffset dx="-4" dy="8" in="blur" result="offset"/>
|
|
||||||
<feComposite in="flood" in2="offset" operator="in" result="comp1"/>
|
|
||||||
<feComposite in="SourceGraphic" in2="comp1" result="comp2"/>
|
|
||||||
</filter>
|
|
||||||
</defs>
|
|
||||||
<!--! Font Awesome Pro 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. -->
|
|
||||||
<path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z" fill="#85c4ff" filter="url(#emblematic-filter)"/>
|
|
||||||
</svg>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.4 KiB |
|
@ -5,8 +5,6 @@
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/micronfig/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/micronfig/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/micronfig/tests" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/micronfig/tests" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/micronfig_macros/src" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/micronfig_macros/tests" isTestSource="true" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "micronfig"
|
name = "micronfig"
|
||||||
version = "1.0.0"
|
version = "0.3.1"
|
||||||
authors = ["Stefano Pigozzi <me@steffo.eu>"]
|
authors = ["Stefano Pigozzi <me@steffo.eu>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Macro-based configuration management"
|
description = "Macro-based configuration management"
|
||||||
|
@ -19,11 +19,8 @@ envfiles = []
|
||||||
envdot = ["regex"]
|
envdot = ["regex"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
micronfig_macros = { version = "1.0.0", path = "../micronfig_macros" }
|
micronfig_macros = { version = "0.3.1", path = "../micronfig_macros" }
|
||||||
regex = { version = "1.10.2", optional = true }
|
regex = { version = "1.10.2", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = { version = "3.9.0" }
|
tempfile = { version = "3.9.0" }
|
||||||
|
|
||||||
[lints.clippy]
|
|
||||||
tabs-in-doc-comments = "allow"
|
|
|
@ -21,7 +21,7 @@ pub fn parse_dotenv<P>(value: P) -> Option<DotEnv>
|
||||||
|
|
||||||
let mut contents: String = String::new();
|
let mut contents: String = String::new();
|
||||||
file.read_to_string(&mut contents)
|
file.read_to_string(&mut contents)
|
||||||
.unwrap_or_else(|_| panic!("to be able to read {value:?}"));
|
.expect(&*format!("to be able to read {value:?}"));
|
||||||
|
|
||||||
let mut keys: HashMap<OsString, String> = HashMap::new();
|
let mut keys: HashMap<OsString, String> = HashMap::new();
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@ pub fn get(key: &OsStr) -> Option<String> {
|
||||||
let path = std::path::PathBuf::from(path);
|
let path = std::path::PathBuf::from(path);
|
||||||
|
|
||||||
let mut file = std::fs::File::open(&path)
|
let mut file = std::fs::File::open(&path)
|
||||||
.unwrap_or_else(|_| panic!("to be able to open file at {path:?}"));
|
.expect(&*format!("to be able to open file at {path:?}"));
|
||||||
|
|
||||||
let mut data = String::new();
|
let mut data = String::new();
|
||||||
file.read_to_string(&mut data)
|
file.read_to_string(&mut data)
|
||||||
.unwrap_or_else(|_| panic!("to be able to read from file at {path:?}"));
|
.expect(&*format!("to be able to read from file at {path:?}"));
|
||||||
|
|
||||||
Some(data)
|
Some(data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,13 +94,11 @@
|
||||||
//! The syntax for conversion is as follows:
|
//! The syntax for conversion is as follows:
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use std::net::SocketAddr;
|
|
||||||
//!
|
|
||||||
//! micronfig::config! {
|
//! micronfig::config! {
|
||||||
//! // use FromStr to parse the String as an isize
|
//! // use FromStr to parse the String as an isize
|
||||||
//! REQUIRED_SIGNED: String > isize,
|
//! REQUIRED_SIGNED: String > isize,
|
||||||
//! // use FromStr to parse the String as a SocketAddr
|
//! // use FromStr to parse the String as a SocketAddr
|
||||||
//! REQUIRED_SOCKETADDR: String > SocketAddr,
|
//! REQUIRED_SOCKETADDR: String > std::net::SocketAddr,
|
||||||
//! // use From to convert the String to... another String
|
//! // use From to convert the String to... another String
|
||||||
//! REQUIRED_STRING: String -> String,
|
//! REQUIRED_STRING: String -> String,
|
||||||
//! // use TryFrom to convert the String to another String
|
//! // use TryFrom to convert the String to another String
|
||||||
|
@ -111,6 +109,10 @@
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
//! > ***Warning***
|
||||||
|
//! >
|
||||||
|
//! > Types should always be fully qualified, or the macro won't work properly!
|
||||||
|
//!
|
||||||
//! Custom types can be used as well:
|
//! Custom types can be used as well:
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
|
@ -129,7 +131,7 @@
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! micronfig::config! {
|
//! micronfig::config! {
|
||||||
//! MY_CUSTOM_TYPE: String -> Duplicator,
|
//! MY_CUSTOM_TYPE: String -> crate::Duplicator,
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! # fn main() {}
|
//! # fn main() {}
|
||||||
|
@ -148,7 +150,7 @@
|
||||||
//!
|
//!
|
||||||
//! micronfig::config! {
|
//! micronfig::config! {
|
||||||
//! // First parse the string as an u64 with FromStr, then convert it to a ChatId with From.
|
//! // First parse the string as an u64 with FromStr, then convert it to a ChatId with From.
|
||||||
//! RESPOND_TO_MESSAGES_IN: String > u64 -> ChatId,
|
//! RESPOND_TO_MESSAGES_IN: String > u64 -> crate::ChatId,
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! # fn main() {}
|
//! # fn main() {}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "micronfig_macros"
|
name = "micronfig_macros"
|
||||||
version = "1.0.0"
|
version = "0.3.1"
|
||||||
authors = ["Stefano Pigozzi <me@steffo.eu>"]
|
authors = ["Stefano Pigozzi <me@steffo.eu>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Macros for micronfig"
|
description = "Macros for micronfig"
|
||||||
|
@ -13,15 +13,12 @@ categories = ["config"]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
syn = { version = "2.0", features = ["extra-traits"] }
|
syn = "2.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
micronfig = { version = "1.0.0", path = "../micronfig" }
|
micronfig = { version = "0.3.1", path = "../micronfig" }
|
||||||
trybuild = "1.0.87"
|
trybuild = "1.0.87"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[lints.clippy]
|
|
||||||
tabs-in-doc-comments = "allow"
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::{quote, ToTokens};
|
||||||
use syn::parse::{Parse, ParseStream};
|
use syn::parse::{Parse, ParseStream};
|
||||||
use syn::{Ident, parse_macro_input, Token, Type, TypePath};
|
use syn::{Ident, parse_macro_input, Token, Type, TypePath};
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
|
|
||||||
|
|
||||||
type Config = Punctuated<ConfigItem, Token![,]>;
|
type Config = Punctuated<ConfigItem, Token![,]>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct ConfigItem {
|
struct ConfigItem {
|
||||||
identifier: Ident,
|
identifier: Ident,
|
||||||
optional: bool,
|
optional: bool,
|
||||||
first: TypePath,
|
|
||||||
types: Vec<ConfigPair>,
|
types: Vec<ConfigPair>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,32 +36,34 @@ impl Parse for ConfigItem {
|
||||||
let optional = input.lookahead1().peek(Token![?]);
|
let optional = input.lookahead1().peek(Token![?]);
|
||||||
if optional {
|
if optional {
|
||||||
input.parse::<Token![?]>()
|
input.parse::<Token![?]>()
|
||||||
.expect("Expected `?`, as it was previously peeked");
|
.expect("this token to be parsed correctly, as it has been previously peeked");
|
||||||
}
|
}
|
||||||
|
|
||||||
let (first, types) = match input.lookahead1().peek(Token![:]) {
|
let types = match input.lookahead1().peek(Token![:]) {
|
||||||
true => {
|
true => {
|
||||||
input.parse::<Token![:]>()
|
input.parse::<Token![:]>()
|
||||||
.expect("Expected `:`, as it was previously peeked");
|
.expect("this token to be parsed correctly, as it has been previously peeked");
|
||||||
|
|
||||||
let first = input.parse::<TypePath>()?;
|
let string_type = input.parse::<TypePath>()?;
|
||||||
|
if &*string_type.to_token_stream().to_string() != "String" {
|
||||||
|
return Err(
|
||||||
|
syn::Error::new_spanned(
|
||||||
|
string_type,
|
||||||
|
"first type of a conversion chain should always be literally `String`, other aliases are not allowed"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let mut types = Vec::new();
|
let mut types = Vec::new();
|
||||||
while let Ok(typ) = input.parse::<ConfigPair>() {
|
while let Ok(typ) = input.parse::<ConfigPair>() {
|
||||||
types.push(typ)
|
types.push(typ)
|
||||||
}
|
}
|
||||||
|
types
|
||||||
(first, types)
|
|
||||||
},
|
|
||||||
false => {
|
|
||||||
let first = syn::parse_quote!(String);
|
|
||||||
let types = Vec::new();
|
|
||||||
|
|
||||||
(first, types)
|
|
||||||
},
|
},
|
||||||
|
false => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self { identifier, optional, first, types })
|
Ok(Self { identifier, optional, types })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,22 +95,23 @@ impl Parse for Conversion {
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn config(input: TokenStream) -> TokenStream {
|
pub fn config(input: TokenStream) -> TokenStream {
|
||||||
let input: Config = parse_macro_input!(input with Punctuated::parse_terminated);
|
let input: Config = parse_macro_input!(input with syn::punctuated::Punctuated::parse_terminated);
|
||||||
|
|
||||||
let cache_code = quote! {
|
let cache_code = quote! {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
mod _cache {
|
||||||
|
pub static _lock: std::sync::OnceLock<micronfig::cache::Cache> = std::sync::OnceLock::new();
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn _cache() -> &'static micronfig::cache::Cache {
|
fn _cache() -> &'static micronfig::cache::Cache {
|
||||||
static LOCK: std::sync::OnceLock<micronfig::cache::Cache> = std::sync::OnceLock::new();
|
_cache::_lock.get_or_init(micronfig::cache::Cache::new)
|
||||||
|
|
||||||
LOCK.get_or_init(micronfig::cache::Cache::new)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let items_code = input.iter().map(|item: &ConfigItem| {
|
let items_code = input.iter().map(|item: &ConfigItem| {
|
||||||
let identifier = &item.identifier;
|
let identifier = &item.identifier;
|
||||||
let identifier_string = identifier.to_string();
|
let identifier_string = identifier.to_string();
|
||||||
|
|
||||||
let type_first = &item.first;
|
|
||||||
|
|
||||||
let type_final = match item.types.last() {
|
let type_final = match item.types.last() {
|
||||||
Some(pair) => {
|
Some(pair) => {
|
||||||
|
@ -134,17 +137,13 @@ pub fn config(input: TokenStream) -> TokenStream {
|
||||||
},
|
},
|
||||||
(Conversion::TryFrom, true) => quote! {
|
(Conversion::TryFrom, true) => quote! {
|
||||||
let value: Option<#typ> = value
|
let value: Option<#typ> = value
|
||||||
.map(|v| v
|
.map(|v| v.try_into())
|
||||||
.try_into()
|
.map(|v| v.expect(&format!("to be able to convert {}", #identifier_string)));
|
||||||
.unwrap_or_else(|err| panic!("{}: Couldn't perform `=> {:?}` conversion: {:#?}", #identifier_string, std::any::type_name::<#typ>(), err))
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
(Conversion::FromStr, true) => quote! {
|
(Conversion::FromStr, true) => quote! {
|
||||||
let value: Option<#typ> = value
|
let value: Option<#typ> = value
|
||||||
.map(|v| v
|
.map(|v| v.parse())
|
||||||
.parse()
|
.map(|v| v.expect(&format!("to be able to parse {}", #identifier_string)));
|
||||||
.unwrap_or_else(|err| panic!("{}: Couldn't perform `> {:?}` conversion: {:#?}", #identifier_string, std::any::type_name::<#typ>(), err))
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
(Conversion::From, false) => quote! {
|
(Conversion::From, false) => quote! {
|
||||||
let value: #typ = value
|
let value: #typ = value
|
||||||
|
@ -153,12 +152,12 @@ pub fn config(input: TokenStream) -> TokenStream {
|
||||||
(Conversion::TryFrom, false) => quote! {
|
(Conversion::TryFrom, false) => quote! {
|
||||||
let value: #typ = value
|
let value: #typ = value
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|err| panic!("{}: Couldn't perform `=> {:?}` conversion: {:#?}", #identifier_string, std::any::type_name::<#typ>(), err));
|
.expect(&format!("to be able to convert {}", #identifier_string));
|
||||||
},
|
},
|
||||||
(Conversion::FromStr, false) => quote! {
|
(Conversion::FromStr, false) => quote! {
|
||||||
let value: #typ = value
|
let value: #typ = value
|
||||||
.parse()
|
.parse()
|
||||||
.unwrap_or_else(|err| panic!("{}: Couldn't perform `> {:?}` conversion: {:#?}", #identifier_string, std::any::type_name::<#typ>(), err));
|
.expect(&format!("to be able to parse {}", #identifier_string));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,18 +169,21 @@ pub fn config(input: TokenStream) -> TokenStream {
|
||||||
true => quote! {},
|
true => quote! {},
|
||||||
false => quote! {
|
false => quote! {
|
||||||
let value: String = value
|
let value: String = value
|
||||||
.unwrap_or_else(|| panic!("{}: Is required, but has no value set", #identifier_string));
|
.expect(&format!("that configuration variable {} was set", #identifier_string));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
mod #identifier {
|
||||||
|
pub(super) static _lock: std::sync::OnceLock<#type_final_option> = std::sync::OnceLock::new();
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub(crate) fn #identifier() -> &'static #type_final_option {
|
pub(crate) fn #identifier() -> &'static #type_final_option {
|
||||||
static LOCK: std::sync::OnceLock<#type_final_option> = std::sync::OnceLock::new();
|
#identifier::_lock.get_or_init(|| {
|
||||||
|
|
||||||
LOCK.get_or_init(|| {
|
|
||||||
let key = #identifier_string.as_ref();
|
let key = #identifier_string.as_ref();
|
||||||
let value: Option<#type_first> = _cache().get(key);
|
let value: Option<std::string::String> = _cache().get(key);
|
||||||
|
|
||||||
#require_code
|
#require_code
|
||||||
#conversion_code
|
#conversion_code
|
||||||
|
@ -191,10 +193,7 @@ pub fn config(input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).reduce(|acc, new| {
|
}).reduce(|acc, new| {
|
||||||
quote! {
|
quote! { #acc #new }
|
||||||
#acc
|
|
||||||
#new
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let quote = quote! {
|
let quote = quote! {
|
||||||
|
|
|
@ -4,14 +4,21 @@ error[E0277]: the trait bound `u64: From<String>` is not satisfied
|
||||||
1 | / micronfig::config! {
|
1 | / micronfig::config! {
|
||||||
2 | | GARASAUTO: String -> u64,
|
2 | | GARASAUTO: String -> u64,
|
||||||
3 | | }
|
3 | | }
|
||||||
| |_^ the trait `From<String>` is not implemented for `u64`, which is required by `String: Into<_>`
|
| | ^
|
||||||
|
| | |
|
||||||
|
| |_the trait `From<String>` is not implemented for `u64`
|
||||||
|
| in this macro invocation
|
||||||
|
|
|
||||||
|
::: src/lib.rs
|
||||||
|
|
|
||||||
|
| pub fn config(input: TokenStream) -> TokenStream {
|
||||||
|
| ------------------------------------------------ in this expansion of `micronfig::config!`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `From<T>`:
|
= help: the following other types implement trait `From<T>`:
|
||||||
`u64` implements `From<Char>`
|
<u64 as From<bool>>
|
||||||
`u64` implements `From<bool>`
|
<u64 as From<char>>
|
||||||
`u64` implements `From<char>`
|
<u64 as From<u8>>
|
||||||
`u64` implements `From<u16>`
|
<u64 as From<u16>>
|
||||||
`u64` implements `From<u32>`
|
<u64 as From<u32>>
|
||||||
`u64` implements `From<u8>`
|
<u64 as From<NonZeroU64>>
|
||||||
= note: required for `String` to implement `Into<u64>`
|
= note: required for `String` to implement `Into<u64>`
|
||||||
= note: this error originates in the macro `micronfig::config` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
|
@ -4,21 +4,25 @@ error[E0277]: the trait bound `Infallible: FromStr` is not satisfied
|
||||||
1 | / micronfig::config! {
|
1 | / micronfig::config! {
|
||||||
2 | | GARASAUTO: String > std::convert::Infallible,
|
2 | | GARASAUTO: String > std::convert::Infallible,
|
||||||
3 | | }
|
3 | | }
|
||||||
| |_^ the trait `FromStr` is not implemented for `Infallible`
|
| | ^
|
||||||
|
| | |
|
||||||
|
| |_the trait `FromStr` is not implemented for `Infallible`
|
||||||
|
| in this macro invocation
|
||||||
|
|
|
||||||
|
::: src/lib.rs
|
||||||
|
|
|
||||||
|
| pub fn config(input: TokenStream) -> TokenStream {
|
||||||
|
| ------------------------------------------------ in this expansion of `micronfig::config!`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `FromStr`:
|
= help: the following other types implement trait `FromStr`:
|
||||||
IpAddr
|
bool
|
||||||
Ipv4Addr
|
char
|
||||||
Ipv6Addr
|
isize
|
||||||
NonZero<i128>
|
i8
|
||||||
NonZero<i16>
|
i16
|
||||||
NonZero<i32>
|
i32
|
||||||
NonZero<i64>
|
i64
|
||||||
NonZero<i8>
|
i128
|
||||||
and $N others
|
and $N others
|
||||||
note: required by a bound in `core::str::<impl str>::parse`
|
note: required by a bound in `core::str::<impl str>::parse`
|
||||||
--> $RUST/core/src/str/mod.rs
|
--> $RUST/core/src/str/mod.rs
|
||||||
|
|
|
||||||
| pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
|
|
||||||
| ^^^^^^^ required by this bound in `core::str::<impl str>::parse`
|
|
||||||
= note: this error originates in the macro `micronfig::config` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
|
@ -1,19 +1,26 @@
|
||||||
error[E0277]: the trait bound `u64: TryFrom<String>` is not satisfied
|
error[E0277]: the trait bound `u64: From<String>` is not satisfied
|
||||||
--> tests/sources/wrong_conversion_trait_tryfrom.rs:1:1
|
--> tests/sources/wrong_conversion_trait_tryfrom.rs:1:1
|
||||||
|
|
|
|
||||||
1 | / micronfig::config! {
|
1 | / micronfig::config! {
|
||||||
2 | | GARASAUTO: String => u64,
|
2 | | GARASAUTO: String => u64,
|
||||||
3 | | }
|
3 | | }
|
||||||
| |_^ the trait `From<String>` is not implemented for `u64`, which is required by `String: TryInto<_>`
|
| | ^
|
||||||
|
| | |
|
||||||
|
| |_the trait `From<String>` is not implemented for `u64`
|
||||||
|
| in this macro invocation
|
||||||
|
|
|
||||||
|
::: src/lib.rs
|
||||||
|
|
|
||||||
|
| pub fn config(input: TokenStream) -> TokenStream {
|
||||||
|
| ------------------------------------------------ in this expansion of `micronfig::config!`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `From<T>`:
|
= help: the following other types implement trait `From<T>`:
|
||||||
`u64` implements `From<Char>`
|
<u64 as From<bool>>
|
||||||
`u64` implements `From<bool>`
|
<u64 as From<char>>
|
||||||
`u64` implements `From<char>`
|
<u64 as From<u8>>
|
||||||
`u64` implements `From<u16>`
|
<u64 as From<u16>>
|
||||||
`u64` implements `From<u32>`
|
<u64 as From<u32>>
|
||||||
`u64` implements `From<u8>`
|
<u64 as From<NonZeroU64>>
|
||||||
= note: required for `String` to implement `Into<u64>`
|
= note: required for `String` to implement `Into<u64>`
|
||||||
= note: required for `u64` to implement `TryFrom<String>`
|
= note: required for `u64` to implement `TryFrom<String>`
|
||||||
= note: required for `String` to implement `TryInto<u64>`
|
= note: required for `String` to implement `TryInto<u64>`
|
||||||
= note: this error originates in the macro `micronfig::config` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
|
@ -1,27 +1,11 @@
|
||||||
error[E0308]: mismatched types
|
error: first type of a conversion chain should always be literally `String`, other aliases are not allowed
|
||||||
--> tests/sources/wrong_start.rs:1:1
|
--> tests/sources/wrong_start.rs:2:13
|
||||||
|
|
|
|
||||||
1 | / micronfig::config! {
|
2 | GARASAUTO: i64,
|
||||||
2 | | GARASAUTO: i64,
|
| ^^^
|
||||||
3 | | }
|
|
||||||
| | ^
|
|
||||||
| | |
|
|
||||||
| |_expected `Option<i64>`, found `Option<String>`
|
|
||||||
| expected due to this
|
|
||||||
|
|
|
||||||
= note: expected enum `Option<i64>`
|
|
||||||
found enum `Option<String>`
|
|
||||||
= note: this error originates in the macro `micronfig::config` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0425]: cannot find function, tuple struct or tuple variant `GARASAUTO` in this scope
|
||||||
--> tests/sources/wrong_start.rs:1:1
|
--> tests/sources/wrong_start.rs:7:20
|
||||||
|
|
|
|
||||||
1 | / micronfig::config! {
|
7 | println!("{:#?}", GARASAUTO());
|
||||||
2 | | GARASAUTO: i64,
|
| ^^^^^^^^^ not found in this scope
|
||||||
3 | | }
|
|
||||||
| | ^- help: try using a conversion method: `.to_string()`
|
|
||||||
| | |
|
|
||||||
| |_expected `String`, found `i64`
|
|
||||||
| expected due to this
|
|
||||||
|
|
|
||||||
= note: this error originates in the macro `micronfig::config` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
error[E0412]: cannot find type `PathBuf` in this scope
|
||||||
|
--> tests/sources/wrong_unqualified_noimport.rs:2:22
|
||||||
|
|
|
||||||
|
2 | GARASAUTO: String > PathBuf,
|
||||||
|
| ^^^^^^^ not found in this scope
|
||||||
|
|
|
||||||
|
= help: consider importing this struct:
|
||||||
|
std::path::PathBuf
|
||||||
|
|
||||||
error[E0412]: cannot find type `PathBuf` in this scope
|
error[E0412]: cannot find type `PathBuf` in this scope
|
||||||
--> tests/sources/wrong_unqualified_noimport.rs:2:22
|
--> tests/sources/wrong_unqualified_noimport.rs:2:22
|
||||||
|
|
|
|
||||||
|
|
|
@ -34,7 +34,6 @@ pass!(string_multi_mixed);
|
||||||
pass!(string_single_explicit);
|
pass!(string_single_explicit);
|
||||||
pass!(string_single_implicit);
|
pass!(string_single_implicit);
|
||||||
pass!(tryfrom_single_custom);
|
pass!(tryfrom_single_custom);
|
||||||
pass!(unqualified_import);
|
|
||||||
|
|
||||||
fail!(wrong_conversion_longfatarrow);
|
fail!(wrong_conversion_longfatarrow);
|
||||||
fail!(wrong_conversion_longthinarrow);
|
fail!(wrong_conversion_longthinarrow);
|
||||||
|
@ -48,4 +47,5 @@ fail!(wrong_nonsense_3);
|
||||||
fail!(wrong_start);
|
fail!(wrong_start);
|
||||||
fail!(wrong_syntax_colon);
|
fail!(wrong_syntax_colon);
|
||||||
fail!(wrong_syntax_type);
|
fail!(wrong_syntax_type);
|
||||||
|
fail!(wrong_unqualified_import);
|
||||||
fail!(wrong_unqualified_noimport);
|
fail!(wrong_unqualified_noimport);
|
||||||
|
|
Loading…
Reference in a new issue