aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2020-03-19 11:51:14 +0000
committerAkshay <[email protected]>2020-03-19 11:51:14 +0000
commita4a7d107fe2c82b1070a72dcf5a6cf5decdaf960 (patch)
tree5d53e0e87abf45a930c407b85767befc72a042e5
parentbf2d5479e353895496b735700ec2ec08713cccc3 (diff)
implement custom path, simpler api
-rw-r--r--fondant_derive/src/lib.rs73
1 files changed, 41 insertions, 32 deletions
diff --git a/fondant_derive/src/lib.rs b/fondant_derive/src/lib.rs
index 946c130..0c66d62 100644
--- a/fondant_derive/src/lib.rs
+++ b/fondant_derive/src/lib.rs
@@ -1,16 +1,15 @@
1extern crate proc_macro; 1extern crate proc_macro;
2 2
3use ::std::ffi::{OsStr, OsString}; 3use ::std::ffi::{OsStr, OsString};
4use ::std::path::{Path, PathBuf}; 4use ::std::path::Path;
5use directories::ProjectDirs;
6use proc_macro::TokenStream; 5use proc_macro::TokenStream;
7use proc_macro2::Span; 6use proc_macro2::Span;
8use quote::quote; 7use quote::quote;
9use syn::{parse_macro_input, DeriveInput, Error, Ident, Lit, Meta, MetaNameValue, Result}; 8use syn::{parse_macro_input, DeriveInput, Ident, Lit, Meta, MetaNameValue};
10 9
11#[derive(Debug, Default)] 10#[derive(Debug, Default)]
12struct ConfigPath { 11struct ConfigPath {
13 parent: Option<PathBuf>, 12 parent: String,
14 filename: Option<OsString>, 13 filename: Option<OsString>,
15 extension: Option<OsString>, 14 extension: Option<OsString>,
16} 15}
@@ -33,13 +32,9 @@ fn extract_attributes(ast: &DeriveInput) -> ConfigPath {
33 if let Lit::Str(f) = lit { 32 if let Lit::Str(f) = lit {
34 let f = f.value(); 33 let f = f.value();
35 let fp = Path::new(&f); 34 let fp = Path::new(&f);
36 let blank = Path::new(""); 35 let parent = fp.parent().unwrap_or(Path::new(""));
37 let parent = match fp.parent() {
38 Some(blank) => None,
39 other => other,
40 };
41 return ConfigPath { 36 return ConfigPath {
42 parent: parent.map(Path::to_path_buf), 37 parent: parent.to_str().unwrap().into(),
43 filename: fp.file_stem().map(OsStr::to_os_string), 38 filename: fp.file_stem().map(OsStr::to_os_string),
44 extension: fp.extension().map(OsStr::to_os_string), 39 extension: fp.extension().map(OsStr::to_os_string),
45 }; 40 };
@@ -80,42 +75,53 @@ fn gen_impl(ast: &DeriveInput, cfg_path: ConfigPath) -> TokenStream {
80 75
81 let filename = cfg_path 76 let filename = cfg_path
82 .filename 77 .filename
83 .unwrap_or(OsStr::new("config").to_os_string()); 78 .unwrap_or(OsStr::new("config").to_os_string())
79 .into_string()
80 .unwrap();
81
84 let filetype = cfg_path 82 let filetype = cfg_path
85 .extension 83 .extension
86 .unwrap_or(OsStr::new("toml").to_os_string()); 84 .unwrap_or(OsStr::new("toml").to_os_string())
87
88 let filename = filename.into_string().unwrap();
89 let filetype = filetype.into_string().unwrap();
90
91 let pkg_name = env!("CARGO_PKG_NAME");
92 let project = ProjectDirs::from("rs", "", pkg_name).unwrap();
93 let default_dir = project.config_dir();
94 let config_dir = cfg_path.parent.as_deref().unwrap_or(default_dir);
95
96 let tip = Path::new(&filename).with_extension(&filetype);
97 let config_file = [config_dir, tip.as_ref()]
98 .iter()
99 .collect::<PathBuf>()
100 .into_os_string()
101 .into_string() 85 .into_string()
102 .unwrap(); 86 .unwrap();
103 let parent: String = config_dir.to_str().unwrap().into(); 87
88 let parent = cfg_path.parent;
104 89
105 let (ser, ser_fn) = pick_serializer(&filetype); 90 let (ser, ser_fn) = pick_serializer(&filetype);
106 91
107 let gen = quote! { 92 let includes = quote! {
108 use ::fondant::{Configure, ProjectDirs, toml, serde_json, serde_yaml, FondantError}; 93 use ::fondant::*;
109 use ::std::option::Option; 94 use ::std::option::Option;
110 use ::std::fs::{self, File, OpenOptions}; 95 use ::std::fs::{self, File, OpenOptions};
111 use ::std::io::prelude::*; 96 use ::std::io::prelude::*;
112 use ::std::io::{ ErrorKind::NotFound, Write }; 97 use ::std::io::{ ErrorKind::NotFound, Write };
113 use ::std::ffi::{OsStr, OsString}; 98 use ::std::ffi::{OsStr, OsString};
114 use ::std::path::{Path, PathBuf}; 99 use ::std::path::{Path, PathBuf};
100 };
115 101
102 let load_paths = quote! {
103 let pkg_name = env!("CARGO_PKG_NAME");
104 let project = ProjectDirs::from("rs", "", pkg_name).unwrap();
105 let default_dir: String = project.config_dir().to_str().unwrap().into();
106
107 let d = if #parent != "" { #parent.into() } else { default_dir };
108 let config_dir: String = expand_tilde(d)
109 .as_path()
110 .to_str()
111 .unwrap()
112 .into();
113
114 let tip = Path::new(&#filename).with_extension(&#filetype);
115 let mut config_file = PathBuf::from(&config_dir);
116 config_file.push(tip);
117 };
118
119 let gen = quote! {
120 #includes
116 impl Configure for #struct_ident { 121 impl Configure for #struct_ident {
117 fn load() -> Result<#struct_ident, FondantError> { 122 fn load() -> Result<#struct_ident, FondantError> {
118 match File::open(&#config_file) { 123 #load_paths
124 match File::open(&config_file) {
119 Ok(mut cfg) => { 125 Ok(mut cfg) => {
120 let mut cfg_data = String::new(); 126 let mut cfg_data = String::new();
121 cfg.read_to_string(&mut cfg_data); 127 cfg.read_to_string(&mut cfg_data);
@@ -125,7 +131,9 @@ fn gen_impl(ast: &DeriveInput, cfg_path: ConfigPath) -> TokenStream {
125 return Ok(config); 131 return Ok(config);
126 }, 132 },
127 Err(ref e) if e.kind() == NotFound => { 133 Err(ref e) if e.kind() == NotFound => {
128 fs::create_dir_all(#parent).map_err(FondantError::DirCreateErr)?; 134 if !Path::new(&config_dir).is_dir() {
135 fs::create_dir_all(config_dir).map_err(FondantError::DirCreateErr)?;
136 }
129 let default_impl = #struct_ident::default(); 137 let default_impl = #struct_ident::default();
130 Configure::store(&default_impl)?; 138 Configure::store(&default_impl)?;
131 return Ok(default_impl); 139 return Ok(default_impl);
@@ -134,11 +142,12 @@ fn gen_impl(ast: &DeriveInput, cfg_path: ConfigPath) -> TokenStream {
134 }; 142 };
135 } 143 }
136 fn store(&self) -> Result<(), FondantError> { 144 fn store(&self) -> Result<(), FondantError> {
145 #load_paths
137 let mut f = OpenOptions::new() 146 let mut f = OpenOptions::new()
138 .write(true) 147 .write(true)
139 .create(true) 148 .create(true)
140 .truncate(true) 149 .truncate(true)
141 .open(#config_file) 150 .open(config_file)
142 .map_err(|_| FondantError::FileOpenError)?; 151 .map_err(|_| FondantError::FileOpenError)?;
143 152
144 let s = #ser::#ser_fn(self).map_err(|_| FondantError::ConfigParseError)?; 153 let s = #ser::#ser_fn(self).map_err(|_| FondantError::ConfigParseError)?;