mirror of https://codeberg.org/topola/topola.git
cleanup: rename macro/ directory to macros/ for naming consistency
This commit is contained in:
parent
99e9675bb0
commit
b63da99584
|
|
@ -37,7 +37,7 @@ log = "0.4"
|
||||||
utf8-chars = "3.0.2"
|
utf8-chars = "3.0.2"
|
||||||
|
|
||||||
[dependencies.specctra_derive]
|
[dependencies.specctra_derive]
|
||||||
path = "macro/specctra_derive"
|
path = "macros/specctra_derive"
|
||||||
|
|
||||||
[dependencies.geo]
|
[dependencies.geo]
|
||||||
version = "0.25.1"
|
version = "0.25.1"
|
||||||
|
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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<Attribute>, name: &str) -> bool {
|
|
||||||
attrs
|
|
||||||
.iter()
|
|
||||||
.find(|attr| attr.path().is_ident(name))
|
|
||||||
.is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn attr_content(attrs: &Vec<Attribute>, name: &str) -> Option<String> {
|
|
||||||
attrs
|
|
||||||
.iter()
|
|
||||||
.find(|attr| attr.path().is_ident(name))
|
|
||||||
.and_then(|attr| Some(attr.parse_args::<LitStr>().expect("string literal").value()))
|
|
||||||
}
|
|
||||||
|
|
@ -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<R: std::io::BufRead> ReadDsn<R> for #name {
|
|
||||||
fn read_dsn(tokenizer: &mut ListTokenizer<R>)
|
|
||||||
-> Result<Self, ParseError>
|
|
||||||
{
|
|
||||||
#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))?,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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<W: std::io::Write> WriteSes<W> for #name {
|
|
||||||
fn write_dsn(&self, writer: &mut ListWriter<W>)
|
|
||||||
-> 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)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue