#![deny(missing_docs)]
mod accepted_rust_type;
mod declarative_env_generator;
mod empty_struct;
mod macro_config;
mod variable_declarations;
use std::path::PathBuf;
use proc_macro::TokenStream;
use proc_macro2::Span;
use syn::{parse_macro_input, Error as SynError};
use crate::{
declarative_env_generator::DeclarativeEnvGenerator, empty_struct::EmptyStruct,
macro_config::MacroConfig, variable_declarations::EnvVariableDeclarations,
};
extern crate proc_macro;
#[proc_macro_attribute]
pub fn declarative_env(attr: TokenStream, item: TokenStream) -> TokenStream {
let macro_config = parse_macro_input!(attr as MacroConfig);
let file_content = match read_env_definition_file(macro_config.path()) {
Ok(c) => c,
Err(e) => return e.to_compile_error().into(),
};
let empty_struct = parse_macro_input!(item as EmptyStruct);
let variable_configs: EnvVariableDeclarations = match macro_config.format() {
macro_config::AcceptedFormat::Hjson => match deser_hjson::from_str(&file_content) {
Ok(v) => v,
Err(e) => {
return SynError::new(Span::call_site(), e)
.to_compile_error()
.into()
}
},
};
DeclarativeEnvGenerator::new(empty_struct, variable_configs).generate()
}
#[doc(hidden)]
fn read_env_definition_file(path: &str) -> Result<String, SynError> {
let cargo_manifest_dir =
std::env::var("CARGO_MANIFEST_DIR").map_err(|it| SynError::new(Span::call_site(), it))?;
let config_file_path = PathBuf::from(cargo_manifest_dir).join(path);
std::fs::read_to_string(config_file_path).map_err(|it| SynError::new(Span::call_site(), it))
}