diff --git a/Cargo.toml b/Cargo.toml index 364457f..b378ede 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ log = "0.4" utf8-chars = "3.0.2" [dependencies.specctra_derive] -path = "macro/specctra_derive" +path = "macros/specctra_derive" [dependencies.geo] version = "0.25.1" diff --git a/macro/specctra_derive/Cargo.toml b/macro/specctra_derive/Cargo.toml deleted file mode 100644 index e3d74b0..0000000 --- a/macro/specctra_derive/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "specctra_derive" -version = "0.1.0" -edition = "2021" - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "1.0.79" -quote = "1.0.35" -syn = "2.0.55" diff --git a/macro/specctra_derive/src/lib.rs b/macro/specctra_derive/src/lib.rs deleted file mode 100644 index a392091..0000000 --- a/macro/specctra_derive/src/lib.rs +++ /dev/null @@ -1,31 +0,0 @@ -use proc_macro::TokenStream; -use syn::{Attribute, DeriveInput, LitStr}; - -mod read; -mod write; - -#[proc_macro_derive(ReadDsn, attributes(opt, anon, vec, anon_vec))] -pub fn derive_read(input: TokenStream) -> TokenStream { - let input = syn::parse_macro_input!(input as DeriveInput); - read::impl_read(&input).into() -} - -#[proc_macro_derive(WriteSes, attributes(anon))] -pub fn derive_write(input: TokenStream) -> TokenStream { - let input = syn::parse_macro_input!(input as DeriveInput); - write::impl_write(&input).into() -} - -fn attr_present(attrs: &Vec, name: &str) -> bool { - attrs - .iter() - .find(|attr| attr.path().is_ident(name)) - .is_some() -} - -fn attr_content(attrs: &Vec, name: &str) -> Option { - attrs - .iter() - .find(|attr| attr.path().is_ident(name)) - .and_then(|attr| Some(attr.parse_args::().expect("string literal").value())) -} diff --git a/macro/specctra_derive/src/read.rs b/macro/specctra_derive/src/read.rs deleted file mode 100644 index cd44a81..0000000 --- a/macro/specctra_derive/src/read.rs +++ /dev/null @@ -1,84 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; -use syn::{Data, DeriveInput, Fields, Field}; -use syn::Type::Path; -use syn::ext::IdentExt; - -use crate::attr_present; -use crate::attr_content; - -pub fn impl_read(input: &DeriveInput) -> TokenStream { - let name = &input.ident; - let body = impl_body(&input.data); - - quote! { - impl ReadDsn for #name { - fn read_dsn(tokenizer: &mut ListTokenizer) - -> Result - { - #body - } - } - } -} - -fn impl_body(data: &Data) -> TokenStream { - match data { - Data::Struct(data) => { - match &data.fields { - Fields::Named(fields) => { - let fields = fields.named.iter().map(|field| { - impl_field(field) - }); - - quote! { - Ok(Self { - #(#fields)* - }) - } - } - _ => unimplemented!() - } - } - Data::Enum(_data) => { - todo!(); - } - _ => unimplemented!() - } -} - -fn impl_field(field: &Field) -> TokenStream { - let name = &field.ident; - let name_str = name.as_ref().expect("field name").unraw(); - - if attr_present(&field.attrs, "anon") { - quote! { - #name: tokenizer.read_value()?, - } - } else if let Some(dsn_name) = attr_content(&field.attrs, "vec") { - quote! { - #name: tokenizer.read_named_array(#dsn_name)?, - } - } else if attr_present(&field.attrs, "anon_vec") { - quote! { - #name: tokenizer.read_array()?, - } - } else { - if let Path(type_path) = &field.ty { - let segments = &type_path.path.segments; - if segments.len() == 1 { - let ident = &segments.first().unwrap().ident; - if ident == "Option" { - return quote! { - #name: tokenizer.read_optional(stringify!(#name_str))?, - } - } - } - } - - quote! { - #name: tokenizer.read_named(stringify!(#name_str))?, - } - } -} - diff --git a/macro/specctra_derive/src/write.rs b/macro/specctra_derive/src/write.rs deleted file mode 100644 index 22db6ad..0000000 --- a/macro/specctra_derive/src/write.rs +++ /dev/null @@ -1,77 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; -use syn::ext::IdentExt; -use syn::Type::Path; -use syn::{Data, DeriveInput, Field, Fields}; - -use crate::attr_content; -use crate::attr_present; - -pub fn impl_write(input: &DeriveInput) -> TokenStream { - let name = &input.ident; - - let body = impl_body(&input.data); - - quote! { - impl WriteSes for #name { - fn write_dsn(&self, writer: &mut ListWriter) - -> std::io::Result<()> - { - #body - } - } - } -} - -fn impl_body(data: &Data) -> TokenStream { - match data { - Data::Struct(data) => match &data.fields { - Fields::Named(fields) => { - let fields = fields.named.iter().map(|field| impl_field(field)); - - quote! { - #(#fields)* - - Ok(()) - } - } - _ => unimplemented!(), - }, - _ => unimplemented!(), - } -} - -fn impl_field(field: &Field) -> TokenStream { - let name = &field.ident; - let name_str = name.as_ref().expect("field name").unraw(); - - if attr_present(&field.attrs, "anon") { - quote! { - writer.write_value(&self.#name)?; - } - } else if let Some(dsn_name) = attr_content(&field.attrs, "vec") { - quote! { - writer.write_named_array(#dsn_name, &self.#name)?; - } - } else if attr_present(&field.attrs, "anon_vec") { - quote! { - writer.write_array(&self.#name)?; - } - } else { - if let Path(type_path) = &field.ty { - let segments = &type_path.path.segments; - if segments.len() == 1 { - let ident = &segments.first().unwrap().ident; - if ident == "Option" { - return quote! { - writer.write_optional(stringify!(#name_str), &self.#name)?; - }; - } - } - } - - quote! { - writer.write_named(stringify!(#name_str), &self.#name)?; - } - } -}