Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs93
1 files changed, 93 insertions, 0 deletions
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()
+}