aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--azalea-buf/azalea-buf-macros/src/read.rs149
-rw-r--r--azalea-buf/azalea-buf-macros/src/write.rs101
-rwxr-xr-xazalea-protocol/src/packets/game/s_container_click.rs2
3 files changed, 156 insertions, 96 deletions
diff --git a/azalea-buf/azalea-buf-macros/src/read.rs b/azalea-buf/azalea-buf-macros/src/read.rs
index 0500ec7c..5f75ad4d 100644
--- a/azalea-buf/azalea-buf-macros/src/read.rs
+++ b/azalea-buf/azalea-buf-macros/src/read.rs
@@ -1,62 +1,6 @@
use quote::{ToTokens, quote};
use syn::{Data, Field, FieldsNamed, Ident, punctuated::Punctuated, token::Comma};
-fn read_named_fields(
- named: &Punctuated<Field, Comma>,
-) -> (Vec<proc_macro2::TokenStream>, Vec<&Option<Ident>>) {
- let read_fields = named
- .iter()
- .map(|f| {
- let field_name = &f.ident;
- let field_type = &f.ty;
-
- let is_variable_length = f.attrs.iter().any(|a| a.path().is_ident("var"));
- let limit = f
- .attrs
- .iter()
- .find(|a| a.path().is_ident("limit"))
- .map(|a| {
- a.parse_args::<syn::LitInt>()
- .unwrap()
- .base10_parse::<usize>()
- .unwrap()
- });
-
- if is_variable_length && limit.is_some() {
- panic!("Fields cannot have both var and limit attributes");
- }
-
- // 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 is_variable_length {
- quote! {
- let #field_name = azalea_buf::AzaleaReadVar::azalea_read_var(buf)?;
- }
- } else if let Some(limit) = limit {
- quote! {
- let #field_name = azalea_buf::AzaleaReadLimited::azalea_read_limited(buf, #limit)?;
- }
- } else {
- quote! {
- let #field_name = azalea_buf::AzaleaRead::azalea_read(buf)?;
- }
- }
- }
- _ => panic!(
- "Error reading field {}: {}",
- field_name.clone().unwrap(),
- field_type.to_token_stream()
- ),
- }
- })
- .collect::<Vec<_>>();
- let read_field_names = named.iter().map(|f| &f.ident).collect::<Vec<_>>();
-
- (read_fields, read_field_names)
-}
-
pub fn create_impl_azalearead(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
match data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
@@ -83,8 +27,18 @@ pub fn create_impl_azalearead(ident: &Ident, data: &Data) -> proc_macro2::TokenS
}
}
}
- _ => {
- panic!("#[derive(AzBuf)] can only be used on structs with named fields")
+ syn::Fields::Unnamed(fields) => {
+ let read_fields = read_unnamed_fields(&fields.unnamed);
+
+ quote! {
+ impl azalea_buf::AzaleaRead for #ident {
+ fn azalea_read(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
+ Ok(Self(
+ #(#read_fields),*
+ ))
+ }
+ }
+ }
}
},
syn::Data::Enum(syn::DataEnum { variants, .. }) => {
@@ -202,3 +156,82 @@ pub fn create_impl_azalearead(ident: &Ident, data: &Data) -> proc_macro2::TokenS
_ => panic!("#[derive(AzBuf)] can only be used on structs"),
}
}
+
+fn read_named_fields(
+ named: &Punctuated<Field, Comma>,
+) -> (Vec<proc_macro2::TokenStream>, Vec<&Option<Ident>>) {
+ let read_fields = named
+ .iter()
+ .map(|f| {
+ let field_name = &f.ident;
+
+ let reader_call = get_reader_call(f);
+ quote! { let #field_name = #reader_call; }
+ })
+ .collect::<Vec<_>>();
+ let read_field_names = named.iter().map(|f| &f.ident).collect::<Vec<_>>();
+
+ (read_fields, read_field_names)
+}
+
+fn read_unnamed_fields(unnamed: &Punctuated<Field, Comma>) -> Vec<proc_macro2::TokenStream> {
+ let read_fields = unnamed
+ .iter()
+ .map(|f| {
+ let reader_call = get_reader_call(f);
+ quote! { #reader_call }
+ })
+ .collect::<Vec<_>>();
+
+ read_fields
+}
+
+fn get_reader_call(f: &Field) -> proc_macro2::TokenStream {
+ let is_variable_length = f
+ .attrs
+ .iter()
+ .any(|a: &syn::Attribute| a.path().is_ident("var"));
+ let limit = f
+ .attrs
+ .iter()
+ .find(|a| a.path().is_ident("limit"))
+ .map(|a| {
+ a.parse_args::<syn::LitInt>()
+ .unwrap()
+ .base10_parse::<usize>()
+ .unwrap()
+ });
+
+ if is_variable_length && limit.is_some() {
+ panic!("Fields cannot have both var and limit attributes");
+ }
+
+ 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
+ let reader_call = match field_type {
+ syn::Type::Path(_) | syn::Type::Array(_) => {
+ if is_variable_length {
+ quote! {
+ azalea_buf::AzaleaReadVar::azalea_read_var(buf)?
+ }
+ } else if let Some(limit) = limit {
+ quote! {
+ azalea_buf::AzaleaReadLimited::azalea_read_limited(buf, #limit)?
+ }
+ } else {
+ quote! {
+ azalea_buf::AzaleaRead::azalea_read(buf)?
+ }
+ }
+ }
+ _ => panic!(
+ "Error reading field {:?}: {}",
+ f.ident.clone(),
+ field_type.to_token_stream()
+ ),
+ };
+
+ reader_call
+}
diff --git a/azalea-buf/azalea-buf-macros/src/write.rs b/azalea-buf/azalea-buf-macros/src/write.rs
index de436e70..d433d1d7 100644
--- a/azalea-buf/azalea-buf-macros/src/write.rs
+++ b/azalea-buf/azalea-buf-macros/src/write.rs
@@ -2,41 +2,6 @@ use proc_macro2::Span;
use quote::{ToTokens, quote};
use syn::{Data, Field, FieldsNamed, Ident, punctuated::Punctuated, token::Comma};
-fn write_named_fields(
- named: &Punctuated<Field, Comma>,
- ident_name: Option<&Ident>,
-) -> proc_macro2::TokenStream {
- let write_fields = named.iter().map(|f| {
- let field_name = &f.ident;
- let field_type = &f.ty;
- let ident_dot_field = match ident_name {
- Some(ident) => quote! { &#ident.#field_name },
- None => quote! { #field_name },
- };
- // 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::AzaleaWriteVar::azalea_write_var(#ident_dot_field, buf)?;
- }
- } else {
- quote! {
- azalea_buf::AzaleaWrite::azalea_write(#ident_dot_field, buf)?;
- }
- }
- }
- _ => panic!(
- "Error writing field {}: {}",
- field_name.clone().unwrap(),
- field_type.to_token_stream()
- ),
- }
- });
- quote! { #(#write_fields)* }
-}
-
pub fn create_impl_azaleawrite(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
match data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
@@ -62,8 +27,17 @@ pub fn create_impl_azaleawrite(ident: &Ident, data: &Data) -> proc_macro2::Token
}
}
}
- _ => {
- panic!("#[derive(AzBuf)] can only be used on structs with named fields")
+ syn::Fields::Unnamed(fields) => {
+ let write_fields = write_unnamed_fields(&fields.unnamed);
+
+ quote! {
+ impl azalea_buf::AzaleaWrite for #ident {
+ fn azalea_write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
+ #write_fields
+ Ok(())
+ }
+ }
+ }
}
},
syn::Data::Enum(syn::DataEnum { variants, .. }) => {
@@ -200,3 +174,56 @@ pub fn create_impl_azaleawrite(ident: &Ident, data: &Data) -> proc_macro2::Token
_ => panic!("#[derive(AzBuf)] can only be used on structs"),
}
}
+
+fn write_named_fields(
+ named: &Punctuated<Field, Comma>,
+ ident_name: Option<&Ident>,
+) -> proc_macro2::TokenStream {
+ let write_fields = named.iter().map(|f| {
+ let field_name = &f.ident;
+ let ident_dot_field = match ident_name {
+ Some(ident) => quote! { &#ident.#field_name },
+ None => quote! { #field_name },
+ };
+
+ make_write_call(f, ident_dot_field)
+ });
+ quote! { #(#write_fields)* }
+}
+
+fn write_unnamed_fields(named: &Punctuated<Field, Comma>) -> proc_macro2::TokenStream {
+ let write_fields = named.iter().enumerate().map(|(i, f)| {
+ let i_literal = syn::Index::from(i);
+ let ident_dot_field = quote! { &self.#i_literal };
+
+ make_write_call(f, ident_dot_field)
+ });
+ quote! { #(#write_fields)* }
+}
+
+fn make_write_call(
+ f: &Field,
+ ident_dot_field: proc_macro2::TokenStream,
+) -> proc_macro2::TokenStream {
+ 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::AzaleaWriteVar::azalea_write_var(#ident_dot_field, buf)?;
+ }
+ } else {
+ quote! {
+ azalea_buf::AzaleaWrite::azalea_write(#ident_dot_field, buf)?;
+ }
+ }
+ }
+ _ => panic!(
+ "Error writing field {:?}: {}",
+ f.ident,
+ field_type.to_token_stream()
+ ),
+ }
+}
diff --git a/azalea-protocol/src/packets/game/s_container_click.rs b/azalea-protocol/src/packets/game/s_container_click.rs
index 2f7ef3d8..ed68de6e 100755
--- a/azalea-protocol/src/packets/game/s_container_click.rs
+++ b/azalea-protocol/src/packets/game/s_container_click.rs
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use azalea_buf::AzBuf;
-use azalea_inventory::{operations::ClickType, ItemStack};
+use azalea_inventory::{ItemStack, operations::ClickType};
use azalea_protocol_macros::ServerboundGamePacket;
#[derive(Clone, Debug, AzBuf, ServerboundGamePacket)]