clams_derive/
lib.rs

1#![recursion_limit = "128"]
2extern crate proc_macro;
3#[macro_use]
4extern crate quote;
5extern crate syn;
6
7use proc_macro::TokenStream;
8
9#[proc_macro_derive(Config)]
10pub fn config(input: TokenStream) -> TokenStream {
11    let input: syn::DeriveInput = syn::parse(input).unwrap();
12
13    // Build the impl
14    let gen = impl_config(&input);
15
16    // Return the generated impl
17    gen.into()
18}
19
20fn impl_config(ast: &syn::DeriveInput) -> quote::Tokens {
21    let name = &ast.ident;
22
23    quote! {
24        use std::path::Path;
25
26        impl Config for #name {
27            type ConfigStruct = #name;
28
29            fn from_file<T: AsRef<Path>>(file_path: T) -> ConfigResult<Self::ConfigStruct> {
30                use std::fs::File;
31                use std::io::Read;
32                use toml;
33
34                let mut file = File::open(file_path)?;
35                let mut content = String::new();
36                file.read_to_string(&mut content)?;
37                let config: Self::ConfigStruct = toml::from_str(&content)?;
38
39                Ok(config)
40            }
41
42            fn smart_load<T: AsRef<Path>>(file_paths: &[T]) -> ConfigResult<(Self::ConfigStruct, &Path)> {
43                for fp in file_paths {
44                    let config = Self::from_file(fp);
45                    if config.is_ok() { return Ok((config.unwrap(), fp.as_ref())) }; // Safe unwrap
46                }
47
48                let failed_configs: Vec<String> = file_paths.iter().map(|x| x.as_ref().to_string_lossy().to_string()).collect();
49                Err(ConfigError::from_kind(ConfigErrorKind::NoSuitableConfigFound(failed_configs)))
50            }
51
52            fn save<T: AsRef<Path>>(&self, file_path: T) -> ConfigResult<()> {
53                use std::fs::File;
54                use std::io::Write;
55                use toml;
56
57                let mut file = File::create(file_path)?;
58                let content = toml::to_string_pretty(self)?;
59                file.write_all(content.as_bytes())?;
60
61                Ok(())
62            }
63
64        }
65    }
66}