diff options
| author | mat <github@matdoes.dev> | 2022-05-01 13:51:59 -0500 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2022-05-01 13:51:59 -0500 |
| commit | 9dacd90abcfaa62ade1e4f130ed53da2c9facdbc (patch) | |
| tree | 68a4956399a6d509a5d8ae790235996a5a24024e /azalea-protocol/packet-macros/src/lib.rs | |
| parent | 4b1cfd1cf899fbbc3de8f72cbb160695c1e9ae70 (diff) | |
| download | azalea-drasl-9dacd90abcfaa62ade1e4f130ed53da2c9facdbc.tar.xz | |
clientbound_add_entity_packet & clientbound_set_entity_data_packet
Diffstat (limited to 'azalea-protocol/packet-macros/src/lib.rs')
| -rwxr-xr-x | azalea-protocol/packet-macros/src/lib.rs | 203 |
1 files changed, 122 insertions, 81 deletions
diff --git a/azalea-protocol/packet-macros/src/lib.rs b/azalea-protocol/packet-macros/src/lib.rs index 0c98f4a3..6d1789a8 100755 --- a/azalea-protocol/packet-macros/src/lib.rs +++ b/azalea-protocol/packet-macros/src/lib.rs @@ -7,105 +7,146 @@ use syn::{ }; fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream { - let fields = match data { - syn::Data::Struct(syn::DataStruct { fields, .. }) => fields, - _ => panic!("#[derive(*Packet)] can only be used on structs"), - }; - let FieldsNamed { named, .. } = match fields { - syn::Fields::Named(f) => f, - _ => panic!("#[derive(*Packet)] can only be used on structs with named fields"), - }; + match data { + syn::Data::Struct(syn::DataStruct { fields, .. }) => { + let FieldsNamed { named, .. } = match fields { + syn::Fields::Named(f) => f, + _ => panic!("#[derive(*Packet)] 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(_) => { - if f.attrs.iter().any(|a| a.path.is_ident("varint")) { - quote! { - let #field_name = crate::mc_buf::McBufVarintReadable::varint_read_into(buf).await?; - } - } else { - quote! { - let #field_name = crate::mc_buf::McBufReadable::read_into(buf).await?; + 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(_) => { + if f.attrs.iter().any(|a| a.path.is_ident("varint")) { + quote! { + let #field_name = crate::mc_buf::McBufVarintReadable::varint_read_into(buf).await?; + } + } else { + quote! { + let #field_name = crate::mc_buf::McBufReadable::read_into(buf).await?; + } } + } + _ => 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<_>>(); + + quote! { + #[async_trait::async_trait] + impl crate::mc_buf::McBufReadable for #ident { + async fn read_into<R>(buf: &mut R) -> Result<Self, String> + where + R: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send, + { + #(#read_fields)* + Ok(#ident { + #(#read_field_names: #read_field_names),* + }) } - _ => 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<_>>(); + } + } + syn::Data::Enum(syn::DataEnum { variants, .. }) => { + let mut match_contents = quote!(); + for variant in variants { + let variant_name = &variant.ident; + let variant_discrim = &variant + .discriminant + .as_ref() + .expect("enum variant must have a discriminant") + .1; + match_contents.extend(quote! { + #variant_discrim => Ok(Self::#variant_name), + }); + } - quote! { - #[async_trait::async_trait] - impl crate::mc_buf::McBufReadable for #ident { - async fn read_into<R>(buf: &mut R) -> Result<Self, String> - where - R: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send, - { - #(#read_fields)* - Ok(#ident { - #(#read_field_names: #read_field_names),* - }) + quote! { + #[async_trait::async_trait] + impl crate::mc_buf::McBufReadable for #ident { + async fn read_into<R>(buf: &mut R) -> Result<Self, String> + where + R: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send, + { + let id = buf.read_varint().await?; + match id { + #match_contents + _ => Err(format!("Unknown enum variant {}", id)), + } + } + } + } } - } + _ => panic!("#[derive(*Packet)] can only be used on structs"), } } fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream { - let fields = match data { - syn::Data::Struct(syn::DataStruct { fields, .. }) => fields, - _ => panic!("#[derive(*Packet)] can only be used on structs"), - }; - let FieldsNamed { named, .. } = match fields { - syn::Fields::Named(f) => f, - _ => panic!("#[derive(*Packet)] can only be used on structs with named fields"), - }; + match data { + syn::Data::Struct(syn::DataStruct { fields, .. }) => { + let FieldsNamed { named, .. } = match fields { + syn::Fields::Named(f) => f, + _ => panic!("#[derive(*Packet)] 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(_) => { - if f.attrs.iter().any(|attr| attr.path.is_ident("varint")) { - quote! { - crate::mc_buf::McBufVarintWritable::varint_write_into(&self.#field_name, buf)?; - } - } else { - quote! { - crate::mc_buf::McBufWritable::write_into(&self.#field_name, buf)?; + 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(_) => { + if f.attrs.iter().any(|attr| attr.path.is_ident("varint")) { + quote! { + crate::mc_buf::McBufVarintWritable::varint_write_into(&self.#field_name, buf)?; + } + } else { + quote! { + crate::mc_buf::McBufWritable::write_into(&self.#field_name, buf)?; + } } } + _ => panic!( + "Error writing field {}: {}", + field_name.clone().unwrap(), + field_type.to_token_stream() + ), } - _ => panic!( - "Error writing field {}: {}", - field_name.clone().unwrap(), - field_type.to_token_stream() - ), - } - }) - .collect::<Vec<_>>(); + }) + .collect::<Vec<_>>(); - quote! { - impl crate::mc_buf::McBufWritable for #ident { - fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> { - #(#write_fields)* - Ok(()) + quote! { + impl crate::mc_buf::McBufWritable for #ident { + fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> { + #(#write_fields)* + Ok(()) + } + } + } + } + syn::Data::Enum(syn::DataEnum { .. }) => { + quote! { + impl crate::mc_buf::McBufWritable for #ident { + fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> { + crate::mc_buf::Writable::write_varint(buf, *self as i32) + } + } } } + _ => panic!("#[derive(*Packet)] can only be used on structs"), } } |
