basic codegen
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Cargo.lock | 52 | ||||
| -rw-r--r-- | Cargo.toml | 13 | ||||
| -rw-r--r-- | src/lib.rs | 93 | ||||
| -rw-r--r-- | tests/x.rs | 6 |
5 files changed, 165 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2fac097 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,52 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "raad" +version = "0.1.2" + +[[package]] +name = "raad-codegen" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "raad", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..290fea8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "raad-codegen" +version = "0.1.0" +edition = "2021" + +[dependencies] +proc-macro2 = "1.0.78" +quote = "1.0.32" +raad = { version = "0.1.2", path = "../raad" } +syn = { version = "2.0.15", features = ["full"] } + +[lib] +proc-macro = true diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..a6e76e2 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,93 @@ +use proc_macro::TokenStream; +use quote::quote; +use spanned::Spanned; +use syn::*; +#[proc_macro_derive(Write, attributes(raad))] +/// Types are written in order of declaration. +pub fn impl_write(input: TokenStream) -> TokenStream { + let DeriveInput { + data, + ident, + vis, + generics, + .. + } = parse_macro_input!(input as DeriveInput); + let Data::Struct(DataStruct { fields, .. }) = data else { + return syn::Error::new(vis.span(), "only structs are supported for codegen") + .to_compile_error() + .into(); + }; + let fields_le = fields + .iter() + .zip((0..).map(proc_macro2::Literal::usize_unsuffixed)) + .map(|(Field { ident, .. }, i)| match ident { + None => quote! { ::raad::le::W::w(to, self.#i)?; }, + Some(i) => quote! { ::raad::le::W::w(to, self.#i)?; }, + }); + let fields_be = fields + .iter() + .zip((0..).map(proc_macro2::Literal::usize_unsuffixed)) + .map(|(Field { ident, .. }, i)| match ident { + None => quote! { ::raad::be::W::w(to, self.#i)?; }, + Some(i) => quote! { ::raad::be::W::w(to, self.#i)?; }, + }); + quote! { + impl ::raad::le::Writable for #ident { + fn _w(self, to: &mut impl ::std::io::Write) -> ::std::io::Result<()> { + #(#fields_le)* + Ok(()) + } + } + impl ::raad::be::Writable for #ident { + fn _w(self, to: &mut impl ::std::io::Write) -> ::std::io::Result<()> { + #(#fields_be)* + Ok(()) + } + } + } + .into() +} + +#[proc_macro_derive(Read, attributes(raad))] +/// Types are read in order of declaration. +pub fn impl_read(input: TokenStream) -> TokenStream { + let DeriveInput { + data, + ident, + vis, + generics, + .. + } = parse_macro_input!(input as DeriveInput); + let Data::Struct(DataStruct { fields, .. }) = data else { + return syn::Error::new(vis.span(), "only structs are supported for codegen") + .to_compile_error() + .into(); + }; + let fields_le = fields + .iter() + .zip((0..).map(proc_macro2::Literal::usize_unsuffixed)) + .map(|(Field { ident, .. }, i)| match ident { + None => quote! { #i: ::raad::le::R::r(from)?, }, + Some(i) => quote! { #i: ::raad::le::R::r(from)?, }, + }); + let fields_be = fields + .iter() + .zip((0..).map(proc_macro2::Literal::usize_unsuffixed)) + .map(|(Field { ident, .. }, i)| match ident { + None => quote! { #i: ::raad::be::R::r(from)?, }, + Some(i) => quote! { #i: ::raad::be::R::r(from)?, }, + }); + quote! { + impl ::raad::le::Readable for #ident { + fn r(from: &mut impl std::io::Read) -> ::std::io::Result<Self> { + Ok(Self { #(#fields_le)* }) + } + } + impl ::raad::be::Readable for #ident { + fn r(from: &mut impl ::std::io::Read) -> ::std::io::Result<Self> { + Ok(Self { #(#fields_be)* }) + } + } + } + .into() +} diff --git a/tests/x.rs b/tests/x.rs new file mode 100644 index 0000000..1a53eee --- /dev/null +++ b/tests/x.rs @@ -0,0 +1,6 @@ +#[derive(raad_codegen::Read, raad_codegen::Write)] +struct X { + y: u8, +} +#[derive(raad_codegen::Write, raad_codegen::Read)] +struct Z(X); |