parsing functions implemented
todo: - implement write_default_config() - implement parse_style_settings()
This commit is contained in:
@@ -9,6 +9,7 @@ publish = false
|
|||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
proc-macro2 = "1.0.92"
|
||||||
quote = "1.0.38"
|
quote = "1.0.38"
|
||||||
syn = { version = "2.0.94", features = ["full", "extra-traits"] }
|
syn = { version = "2.0.94", features = ["full", "extra-traits"] }
|
||||||
|
|
||||||
|
|||||||
+22
-16
@@ -1,39 +1,45 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use syn::{parse_macro_input, DeriveInput};
|
use quote::{quote, TokenStreamExt};
|
||||||
use quote::{quote};
|
|
||||||
|
|
||||||
use syn::{Attribute, Error, Field, Meta, Path, punctuated::Punctuated, token::Comma};
|
use syn::{Attribute, Error, Field, Meta, Path, punctuated::Punctuated, token::Comma};
|
||||||
|
|
||||||
pub fn gen_config_load_function(fields: &Punctuated<Field, Comma>, config_map_name: &String) -> Result<TokenStream, Error> {
|
pub fn gen_config_load_function(fields: &Punctuated<Field, Comma>, config_map_name: &syn::Ident) -> Result<TokenStream, Error> {
|
||||||
let assignments = fields.iter().map(|f|{
|
let mut assignments : TokenStream = TokenStream::new();
|
||||||
let attr = &f.attrs;
|
'field_loop: for field in fields.iter() {
|
||||||
let name = match &f.ident {
|
let attr = &field.attrs;
|
||||||
|
let name = match &field.ident {
|
||||||
Some(value) => value,
|
Some(value) => value,
|
||||||
// skip anonymous fields
|
// skip anonymous fields
|
||||||
None => return quote! {},
|
None => continue 'field_loop,
|
||||||
};
|
};
|
||||||
let name_string: String = name.to_string();
|
let name_string: String = name.to_string();
|
||||||
let ty = &f.ty;
|
let ty = &field.ty;
|
||||||
for attribute in attr {
|
for attribute in attr {
|
||||||
if let Attribute{ meta: Meta::Path( Path{segments: attr_name, ..} ), .. } = attribute {
|
if let Attribute{ meta: Meta::Path( Path{segments: attr_name, ..} ), .. } = attribute {
|
||||||
match attr_name.first() {
|
match attr_name.first() {
|
||||||
Some(value) => if value.ident == "nested_config" {
|
Some(value) => if value.ident == "nested_config" {
|
||||||
return quote! {#name.parse_from_map(&#config_map_name)}
|
assignments.extend(quote! {
|
||||||
|
self.#name.parse_from_map(&#config_map_name);
|
||||||
|
});
|
||||||
|
continue 'field_loop;
|
||||||
},
|
},
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
quote! {
|
assignments.extend(quote! {
|
||||||
self.#name = match #config_map_name.get(#name_string) {
|
self.#name = match #config_map_name.get(#name_string) {
|
||||||
Some(value) => value,
|
Some(value) => match value.parse::<#ty>() {
|
||||||
None => self.#name,
|
Ok(parsed) => parsed,
|
||||||
}
|
Err(_) => self.#name.clone(),
|
||||||
}
|
},
|
||||||
|
None => self.#name.clone(),
|
||||||
|
};
|
||||||
});
|
});
|
||||||
Ok(quote! {assignments}.into())
|
}
|
||||||
|
Ok(assignments.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
//pub fn parse_config_file(input: &String) -> std::io::Result<std::collections::HashMap<String, String>> {
|
//pub fn parse_config_file(input: &String) -> std::io::Result<std::collections::HashMap<String, String>> {
|
||||||
|
|||||||
+20
-15
@@ -1,5 +1,5 @@
|
|||||||
use common::gen_config_load_function;
|
use common::gen_config_load_function;
|
||||||
use proc_macro::{TokenStream}; // TODO: change to proc_macro2, to hopefully fix #assignments
|
use proc_macro2::{TokenStream}; // TODO: change to proc_macro2, to hopefully fix #assignments
|
||||||
use syn::{parse_macro_input, spanned::Spanned, DeriveInput, Ident};
|
use syn::{parse_macro_input, spanned::Spanned, DeriveInput, Ident};
|
||||||
use quote::{quote};
|
use quote::{quote};
|
||||||
|
|
||||||
@@ -11,11 +11,11 @@ mod common;
|
|||||||
/// which parses a string and fills the fills recognised values into the struct
|
/// which parses a string and fills the fills recognised values into the struct
|
||||||
/// - implements `write_default_config() -> Result<String>`
|
/// - implements `write_default_config() -> Result<String>`
|
||||||
/// which write a default configuration, in case the documentation is lacking
|
/// which write a default configuration, in case the documentation is lacking
|
||||||
#[proc_macro_derive(ConfigParser, attributes(nested_config, testtest))]
|
#[proc_macro_derive(ConfigParser, attributes(nested_config))]
|
||||||
pub fn derive(input: TokenStream) -> TokenStream {
|
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let ast = parse_macro_input!(input as DeriveInput);
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
let config_name = "config".to_string(); //syn::Ident::new("config", name.span()); // TODO: use correct span
|
let config_name = syn::Ident::new("config", name.span()); // TODO: use correct span
|
||||||
let fields = if let syn::Data::Struct(syn::DataStruct{ fields: syn::Fields::Named(syn::FieldsNamed{ ref named, .. }), .. }) = ast.data {
|
let fields = if let syn::Data::Struct(syn::DataStruct{ fields: syn::Fields::Named(syn::FieldsNamed{ ref named, .. }), .. }) = ast.data {
|
||||||
named
|
named
|
||||||
} else {
|
} else {
|
||||||
@@ -23,17 +23,9 @@ pub fn derive(input: TokenStream) -> TokenStream {
|
|||||||
};
|
};
|
||||||
let assignments = match gen_config_load_function(fields, &config_name) {
|
let assignments = match gen_config_load_function(fields, &config_name) {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(error) => panic!("loading config failed"),
|
Err(_) => panic!("loading config failed"),
|
||||||
};
|
};
|
||||||
|
|
||||||
//let assign_fields = fields.iter().map(|f|{
|
|
||||||
// if let Some(name) = &f.ident {
|
|
||||||
// quote! {
|
|
||||||
// if
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//});
|
|
||||||
|
|
||||||
//let string = format!("{:#?}", ast);
|
//let string = format!("{:#?}", ast);
|
||||||
//_ = std::fs::write("test.txt", string);
|
//_ = std::fs::write("test.txt", string);
|
||||||
|
|
||||||
@@ -41,7 +33,9 @@ pub fn derive(input: TokenStream) -> TokenStream {
|
|||||||
impl #name {
|
impl #name {
|
||||||
pub fn parse_from_string(&mut self, input: &String) -> std::io::Result<()> {
|
pub fn parse_from_string(&mut self, input: &String) -> std::io::Result<()> {
|
||||||
let #config_name : std::collections::HashMap<String, String> = Self::parse_config_file(input)?;
|
let #config_name : std::collections::HashMap<String, String> = Self::parse_config_file(input)?;
|
||||||
|
|
||||||
#assignments
|
#assignments
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +43,11 @@ pub fn derive(input: TokenStream) -> TokenStream {
|
|||||||
/// this function needs to be public for nested configs but is not intended
|
/// this function needs to be public for nested configs but is not intended
|
||||||
/// to be called by the user
|
/// to be called by the user
|
||||||
pub fn parse_from_map(&mut self, input: &std::collections::HashMap<String, String>) -> std::io::Result<()> {
|
pub fn parse_from_map(&mut self, input: &std::collections::HashMap<String, String>) -> std::io::Result<()> {
|
||||||
todo!();
|
let #config_name = input;
|
||||||
|
|
||||||
|
#assignments
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_config_file(input: &String) -> std::io::Result<std::collections::HashMap<String, String>> {
|
fn parse_config_file(input: &String) -> std::io::Result<std::collections::HashMap<String, String>> {
|
||||||
@@ -84,9 +82,16 @@ pub fn derive(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
pub fn write_default_config(&self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement function to parse style settings
|
||||||
}
|
}
|
||||||
}.into();
|
}.into();
|
||||||
expanded_stream
|
expanded_stream.into()
|
||||||
//TokenStream::new()
|
//TokenStream::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user