Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions from-env-derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "init4-from-env-derive"

description = "A derive macro for `init4_bin_base::FromEnv`"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
rust-version = "1.81"
authors = ["init4", "James Prestwich"]
Expand All @@ -20,4 +20,4 @@ syn = { version = "2.0.100", features = ["full", "parsing"] }
proc-macro = true

[dev-dependencies]
init4-bin-base = "0.3"
init4-bin-base = "0.9"
4 changes: 2 additions & 2 deletions from-env-derive/src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl Field {
return field_name.clone();
}

let n = format!("field_{}", idx);
let n = format!("field_{idx}");
syn::parse_str::<Ident>(&n)
.map_err(|_| syn::Error::new(self.span, "Failed to create field name"))
.unwrap()
Expand Down Expand Up @@ -199,7 +199,7 @@ impl Field {
})
}

pub(crate) fn expand_item_from_env(&self, err_ident: &Ident, idx: usize) -> TokenStream {
pub(crate) fn expand_item_from_env(&self, err_ident: &syn::Path, idx: usize) -> TokenStream {
// Produces code fo the following form:
// ```rust
// // EITHER
Expand Down
32 changes: 27 additions & 5 deletions from-env-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,23 @@ impl Input {
}
}

fn error_ident(&self) -> syn::Ident {
fn error_ident(&self) -> syn::Path {
if self.is_infallible() {
return syn::parse_str("::std::convert::Infallible").unwrap();
}

let error_name = format!("{}EnvError", self.ident);
syn::parse_str::<syn::Ident>(&error_name)
syn::parse_str::<syn::Path>(&error_name)
.map_err(|_| {
syn::Error::new(self.ident.span(), "Failed to parse error ident").to_compile_error()
})
.unwrap()
}

fn is_infallible(&self) -> bool {
self.error_variants().is_empty()
}

fn error_variants(&self) -> Vec<TokenStream> {
self.fields
.iter()
Expand Down Expand Up @@ -152,6 +160,10 @@ impl Input {
let error_variant_displays = self.error_variant_displays();
let error_variant_sources = self.expand_variant_sources();

if error_variants.is_empty() {
return Default::default();
}

quote! {
#[doc = "Generated error type for [`FromEnv`] for"]
#[doc = #struct_name_str]
Expand Down Expand Up @@ -195,6 +207,7 @@ impl Input {
fn expand_impl(&self) -> TokenStream {
let env_item_info = self.env_item_info();
let struct_name = &self.ident;

let error_ident = self.error_ident();

let item_from_envs = self.item_from_envs();
Expand Down Expand Up @@ -226,16 +239,25 @@ impl Input {

fn expand_mod(&self) -> TokenStream {
// let expanded_impl = expand_impl(input);
let expanded_error = self.expand_error();
let expanded_impl = self.expand_impl();
let crate_name = &self.crate_name;
let error_ident = self.error_ident();

let mod_ident =
syn::parse_str::<syn::Ident>(&format!("__from_env_impls_{}", self.ident)).unwrap();

let expanded_error = self.expand_error();

let use_err = if !expanded_error.is_empty() {
let error_ident = self.error_ident();
quote! {
pub use #mod_ident::#error_ident;
}
} else {
quote! {}
};

quote! {
pub use #mod_ident::#error_ident;
#use_err
mod #mod_ident {
use super::*;
use #crate_name::utils::from_env::{FromEnv, FromEnvErr, FromEnvVar, EnvItemInfo};
Expand Down
19 changes: 15 additions & 4 deletions from-env-derive/tests/macro.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
use init4_from_env_derive::FromEnv;

// Compile check for a struct with no fallible fields (and therefore no
// associated env error).
#[derive(Debug, FromEnv)]
pub struct InfallibleConfig {
#[from_env(var = "INTERNAL", desc = "An infallible string", infallible)]
pub internal: String,

#[from_env(var = "INTERNAL_COW", desc = "An infallible Cow<str>", infallible)]
pub internal_cow: std::borrow::Cow<'static, str>,
}

#[derive(FromEnv, Debug)]
pub struct FromEnvTest {
/// This is a guy named tony
Expand Down Expand Up @@ -81,10 +92,10 @@ mod test {
}

fn assert_contains(vec: &Vec<&'static EnvItemInfo>, item: &EnvItemInfo) {
let item = vec.iter().find(|i| i.var == item.var).unwrap();
assert_eq!(item.var, item.var);
assert_eq!(item.description, item.description);
assert_eq!(item.optional, item.optional);
let i = vec.iter().find(|i| i.var == item.var).unwrap();
assert_eq!(i.var, item.var);
assert_eq!(i.description, item.description);
assert_eq!(i.optional, item.optional);
}

#[test]
Expand Down