basic codegen
bendn 2024-09-09
commit 02a1ec9
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock52
-rw-r--r--Cargo.toml13
-rw-r--r--src/lib.rs93
-rw-r--r--tests/x.rs6
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);