From d9d7b87d6170a4a087f1919d6efa390db6932083 Mon Sep 17 00:00:00 2001 From: mat Date: Mon, 29 Aug 2022 21:09:57 -0500 Subject: buf macros -> azalea-buf-macros --- azalea-buf/Cargo.toml | 2 +- azalea-buf/azalea-buf-macros/Cargo.toml | 14 +++ azalea-buf/azalea-buf-macros/README.md | 1 + azalea-buf/azalea-buf-macros/src/lib.rs | 182 ++++++++++++++++++++++++++++++++ azalea-buf/buf-macros/Cargo.toml | 14 --- azalea-buf/buf-macros/src/lib.rs | 182 -------------------------------- 6 files changed, 198 insertions(+), 197 deletions(-) create mode 100644 azalea-buf/azalea-buf-macros/Cargo.toml create mode 100644 azalea-buf/azalea-buf-macros/README.md create mode 100644 azalea-buf/azalea-buf-macros/src/lib.rs delete mode 100644 azalea-buf/buf-macros/Cargo.toml delete mode 100644 azalea-buf/buf-macros/src/lib.rs diff --git a/azalea-buf/Cargo.toml b/azalea-buf/Cargo.toml index 80380a3b..71ce4592 100644 --- a/azalea-buf/Cargo.toml +++ b/azalea-buf/Cargo.toml @@ -6,7 +6,7 @@ version = "0.1.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -buf-macros = {path = "./buf-macros", version = "*"} +buf-macros = {path = "./azalea-buf-macros", version = "*"} byteorder = "^1.4.3" serde_json = {version = "^1.0", optional = true} thiserror = "^1.0.31" diff --git a/azalea-buf/azalea-buf-macros/Cargo.toml b/azalea-buf/azalea-buf-macros/Cargo.toml new file mode 100644 index 00000000..98d028e9 --- /dev/null +++ b/azalea-buf/azalea-buf-macros/Cargo.toml @@ -0,0 +1,14 @@ +[package] +edition = "2021" +name = "buf-macros" +version = "0.1.0" + +[lib] +proc-macro = true +publish = false +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +proc-macro2 = "^1.0.36" +quote = "^1.0.10" +syn = {version = "^1.0.82", features = ["extra-traits"]} diff --git a/azalea-buf/azalea-buf-macros/README.md b/azalea-buf/azalea-buf-macros/README.md new file mode 100644 index 00000000..b9622991 --- /dev/null +++ b/azalea-buf/azalea-buf-macros/README.md @@ -0,0 +1 @@ +Only used in azalea-buf. \ No newline at end of file diff --git a/azalea-buf/azalea-buf-macros/src/lib.rs b/azalea-buf/azalea-buf-macros/src/lib.rs new file mode 100644 index 00000000..43e60e6e --- /dev/null +++ b/azalea-buf/azalea-buf-macros/src/lib.rs @@ -0,0 +1,182 @@ +use proc_macro::TokenStream; +use quote::{quote, ToTokens}; +use syn::{self, parse_macro_input, Data, DeriveInput, FieldsNamed, Ident}; + +fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream { + match data { + syn::Data::Struct(syn::DataStruct { fields, .. }) => { + let FieldsNamed { named, .. } = match fields { + syn::Fields::Named(f) => f, + _ => panic!("#[derive(McBuf)] can only be used on structs with named fields"), + }; + + let read_fields = named + .iter() + .map(|f| { + let field_name = &f.ident; + let field_type = &f.ty; + // do a different buf.write_* for each field depending on the type + // if it's a string, use buf.write_string + match field_type { + syn::Type::Path(_) | syn::Type::Array(_) => { + if f.attrs.iter().any(|a| a.path.is_ident("var")) { + quote! { + let #field_name = azalea_buf::McBufVarReadable::var_read_from(buf)?; + } + } else { + quote! { + let #field_name = azalea_buf::McBufReadable::read_from(buf)?; + } + } + } + _ => panic!( + "Error reading field {}: {}", + field_name.clone().unwrap(), + field_type.to_token_stream() + ), + } + }) + .collect::>(); + let read_field_names = named.iter().map(|f| &f.ident).collect::>(); + + quote! { + impl azalea_buf::McBufReadable for #ident { + fn read_from(buf: &mut impl std::io::Read) -> Result { + #(#read_fields)* + Ok(#ident { + #(#read_field_names: #read_field_names),* + }) + } + } + } + } + syn::Data::Enum(syn::DataEnum { variants, .. }) => { + let mut match_contents = quote!(); + let mut variant_discrim: u32 = 0; + for variant in variants { + let variant_name = &variant.ident; + match &variant.discriminant.as_ref() { + Some(d) => { + variant_discrim = match &d.1 { + syn::Expr::Lit(e) => match &e.lit { + syn::Lit::Int(i) => i.base10_parse().unwrap(), + _ => panic!("Error parsing enum discriminant as int"), + }, + syn::Expr::Unary(_) => { + panic!("Negative enum discriminants are not supported") + } + _ => { + panic!("Error parsing enum discriminant as literal (is {:?})", d.1) + } + } + } + None => { + variant_discrim += 1; + } + } + match_contents.extend(quote! { + #variant_discrim => Ok(Self::#variant_name), + }); + } + + quote! { + impl azalea_buf::McBufReadable for #ident { + fn read_from(buf: &mut impl std::io::Read) -> Result + { + let id = azalea_buf::McBufVarReadable::var_read_from(buf)?; + match id { + #match_contents + _ => Err(azalea_buf::BufReadError::UnexpectedEnumVariant { id: id as i32 }), + } + } + } + } + } + _ => panic!("#[derive(McBuf)] can only be used on structs"), + } +} + +fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream { + match data { + syn::Data::Struct(syn::DataStruct { fields, .. }) => { + let FieldsNamed { named, .. } = match fields { + syn::Fields::Named(f) => f, + _ => panic!("#[derive(McBuf)] can only be used on structs with named fields"), + }; + + let write_fields = named + .iter() + .map(|f| { + let field_name = &f.ident; + let field_type = &f.ty; + // do a different buf.write_* for each field depending on the type + // if it's a string, use buf.write_string + match field_type { + syn::Type::Path(_) | syn::Type::Array(_) => { + if f.attrs.iter().any(|attr| attr.path.is_ident("var")) { + quote! { + azalea_buf::McBufVarWritable::var_write_into(&self.#field_name, buf)?; + } + } else { + quote! { + azalea_buf::McBufWritable::write_into(&self.#field_name, buf)?; + } + } + } + _ => panic!( + "Error writing field {}: {}", + field_name.clone().unwrap(), + field_type.to_token_stream() + ), + } + }) + .collect::>(); + + quote! { + impl azalea_buf::McBufWritable for #ident { + fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> { + #(#write_fields)* + Ok(()) + } + } + } + } + syn::Data::Enum(syn::DataEnum { .. }) => { + quote! { + impl azalea_buf::McBufWritable for #ident { + fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> { + azalea_buf::Writable::write_varint(buf, *self as i32) + } + } + } + } + _ => panic!("#[derive(McBuf)] can only be used on structs"), + } +} + +#[proc_macro_derive(McBufReadable, attributes(var))] +pub fn derive_mcbufreadable(input: TokenStream) -> TokenStream { + let DeriveInput { ident, data, .. } = parse_macro_input!(input); + + create_impl_mcbufreadable(&ident, &data).into() +} + +#[proc_macro_derive(McBufWritable, attributes(var))] +pub fn derive_mcbufwritable(input: TokenStream) -> TokenStream { + let DeriveInput { ident, data, .. } = parse_macro_input!(input); + + create_impl_mcbufwritable(&ident, &data).into() +} + +#[proc_macro_derive(McBuf, attributes(var))] +pub fn derive_mcbuf(input: TokenStream) -> TokenStream { + let DeriveInput { ident, data, .. } = parse_macro_input!(input); + + let writable = create_impl_mcbufwritable(&ident, &data); + let readable = create_impl_mcbufreadable(&ident, &data); + quote! { + #writable + #readable + } + .into() +} diff --git a/azalea-buf/buf-macros/Cargo.toml b/azalea-buf/buf-macros/Cargo.toml deleted file mode 100644 index 98d028e9..00000000 --- a/azalea-buf/buf-macros/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -edition = "2021" -name = "buf-macros" -version = "0.1.0" - -[lib] -proc-macro = true -publish = false -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -proc-macro2 = "^1.0.36" -quote = "^1.0.10" -syn = {version = "^1.0.82", features = ["extra-traits"]} diff --git a/azalea-buf/buf-macros/src/lib.rs b/azalea-buf/buf-macros/src/lib.rs deleted file mode 100644 index 43e60e6e..00000000 --- a/azalea-buf/buf-macros/src/lib.rs +++ /dev/null @@ -1,182 +0,0 @@ -use proc_macro::TokenStream; -use quote::{quote, ToTokens}; -use syn::{self, parse_macro_input, Data, DeriveInput, FieldsNamed, Ident}; - -fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream { - match data { - syn::Data::Struct(syn::DataStruct { fields, .. }) => { - let FieldsNamed { named, .. } = match fields { - syn::Fields::Named(f) => f, - _ => panic!("#[derive(McBuf)] can only be used on structs with named fields"), - }; - - let read_fields = named - .iter() - .map(|f| { - let field_name = &f.ident; - let field_type = &f.ty; - // do a different buf.write_* for each field depending on the type - // if it's a string, use buf.write_string - match field_type { - syn::Type::Path(_) | syn::Type::Array(_) => { - if f.attrs.iter().any(|a| a.path.is_ident("var")) { - quote! { - let #field_name = azalea_buf::McBufVarReadable::var_read_from(buf)?; - } - } else { - quote! { - let #field_name = azalea_buf::McBufReadable::read_from(buf)?; - } - } - } - _ => panic!( - "Error reading field {}: {}", - field_name.clone().unwrap(), - field_type.to_token_stream() - ), - } - }) - .collect::>(); - let read_field_names = named.iter().map(|f| &f.ident).collect::>(); - - quote! { - impl azalea_buf::McBufReadable for #ident { - fn read_from(buf: &mut impl std::io::Read) -> Result { - #(#read_fields)* - Ok(#ident { - #(#read_field_names: #read_field_names),* - }) - } - } - } - } - syn::Data::Enum(syn::DataEnum { variants, .. }) => { - let mut match_contents = quote!(); - let mut variant_discrim: u32 = 0; - for variant in variants { - let variant_name = &variant.ident; - match &variant.discriminant.as_ref() { - Some(d) => { - variant_discrim = match &d.1 { - syn::Expr::Lit(e) => match &e.lit { - syn::Lit::Int(i) => i.base10_parse().unwrap(), - _ => panic!("Error parsing enum discriminant as int"), - }, - syn::Expr::Unary(_) => { - panic!("Negative enum discriminants are not supported") - } - _ => { - panic!("Error parsing enum discriminant as literal (is {:?})", d.1) - } - } - } - None => { - variant_discrim += 1; - } - } - match_contents.extend(quote! { - #variant_discrim => Ok(Self::#variant_name), - }); - } - - quote! { - impl azalea_buf::McBufReadable for #ident { - fn read_from(buf: &mut impl std::io::Read) -> Result - { - let id = azalea_buf::McBufVarReadable::var_read_from(buf)?; - match id { - #match_contents - _ => Err(azalea_buf::BufReadError::UnexpectedEnumVariant { id: id as i32 }), - } - } - } - } - } - _ => panic!("#[derive(McBuf)] can only be used on structs"), - } -} - -fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream { - match data { - syn::Data::Struct(syn::DataStruct { fields, .. }) => { - let FieldsNamed { named, .. } = match fields { - syn::Fields::Named(f) => f, - _ => panic!("#[derive(McBuf)] can only be used on structs with named fields"), - }; - - let write_fields = named - .iter() - .map(|f| { - let field_name = &f.ident; - let field_type = &f.ty; - // do a different buf.write_* for each field depending on the type - // if it's a string, use buf.write_string - match field_type { - syn::Type::Path(_) | syn::Type::Array(_) => { - if f.attrs.iter().any(|attr| attr.path.is_ident("var")) { - quote! { - azalea_buf::McBufVarWritable::var_write_into(&self.#field_name, buf)?; - } - } else { - quote! { - azalea_buf::McBufWritable::write_into(&self.#field_name, buf)?; - } - } - } - _ => panic!( - "Error writing field {}: {}", - field_name.clone().unwrap(), - field_type.to_token_stream() - ), - } - }) - .collect::>(); - - quote! { - impl azalea_buf::McBufWritable for #ident { - fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> { - #(#write_fields)* - Ok(()) - } - } - } - } - syn::Data::Enum(syn::DataEnum { .. }) => { - quote! { - impl azalea_buf::McBufWritable for #ident { - fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> { - azalea_buf::Writable::write_varint(buf, *self as i32) - } - } - } - } - _ => panic!("#[derive(McBuf)] can only be used on structs"), - } -} - -#[proc_macro_derive(McBufReadable, attributes(var))] -pub fn derive_mcbufreadable(input: TokenStream) -> TokenStream { - let DeriveInput { ident, data, .. } = parse_macro_input!(input); - - create_impl_mcbufreadable(&ident, &data).into() -} - -#[proc_macro_derive(McBufWritable, attributes(var))] -pub fn derive_mcbufwritable(input: TokenStream) -> TokenStream { - let DeriveInput { ident, data, .. } = parse_macro_input!(input); - - create_impl_mcbufwritable(&ident, &data).into() -} - -#[proc_macro_derive(McBuf, attributes(var))] -pub fn derive_mcbuf(input: TokenStream) -> TokenStream { - let DeriveInput { ident, data, .. } = parse_macro_input!(input); - - let writable = create_impl_mcbufwritable(&ident, &data); - let readable = create_impl_mcbufreadable(&ident, &data); - quote! { - #writable - #readable - } - .into() -} -- cgit v1.2.3