mirror of
https://github.com/OMGeeky/mc-server-rs-sample.git
synced 2026-02-23 15:49:54 +01:00
create macro to not duplicate as much code and improve the PackageId parsing with it
This commit is contained in:
47
mc-rust-server-macros/Cargo.lock
generated
Normal file
47
mc-rust-server-macros/Cargo.lock
generated
Normal file
@@ -0,0 +1,47 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "mc-rust-server-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
|
||||
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 = "syn"
|
||||
version = "2.0.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||
14
mc-rust-server-macros/Cargo.toml
Normal file
14
mc-rust-server-macros/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "mc-rust-server-macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "mc_rust_server_macros"
|
||||
path = "src/lib.rs"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "*"
|
||||
syn = { version = "*", features = ["extra-traits"] }
|
||||
proc-macro2 = "*"
|
||||
9
mc-rust-server-macros/src/lib.rs
Normal file
9
mc-rust-server-macros/src/lib.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
extern crate proc_macro;
|
||||
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(McProtocol, attributes(protocol_read, protocol_write))]
|
||||
pub fn proc_macro_protocol(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
mc_protocol::proc_macro_protocol(parse_macro_input!(input as DeriveInput)).into()
|
||||
}
|
||||
mod mc_protocol;
|
||||
78
mc-rust-server-macros/src/mc_protocol.rs
Normal file
78
mc-rust-server-macros/src/mc_protocol.rs
Normal file
@@ -0,0 +1,78 @@
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::quote;
|
||||
use syn::parse::Parse;
|
||||
use syn::{Data, DeriveInput, Lit, Token};
|
||||
|
||||
pub fn proc_macro_protocol(input: DeriveInput) -> TokenStream {
|
||||
match input.data {
|
||||
Data::Enum(e) => {
|
||||
let variants = e.variants.into_iter();
|
||||
let mut variant_data = vec![];
|
||||
for v in variants {
|
||||
let attr = v.attrs.into_iter().find_map(|a| {
|
||||
if a.path().is_ident("protocol_read") {
|
||||
Some(a.parse_args::<ProtocolAttribute>().ok()?)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
if let Some(attr) = attr {
|
||||
variant_data.push(ProtocolVariant {
|
||||
attr,
|
||||
ident: v.ident,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let variant_match = variant_data.into_iter().map(|v| {
|
||||
let state = v.attr.state;
|
||||
let id = v.attr.packet_id;
|
||||
let name = v.ident;
|
||||
quote! {(#state, #id)=>Self::#name (read_protocol_data(stream).await?)}
|
||||
});
|
||||
let variants_match = quote! {#(#variant_match),*};
|
||||
|
||||
let enum_name = input.ident;
|
||||
quote! {
|
||||
#[automatically_derived]
|
||||
impl #enum_name {
|
||||
pub async fn read_protocol_data<T:AsyncRead + AsyncWrite + Unpin>(
|
||||
protocol_id: VarInt,
|
||||
connection_state: ConnectionState,
|
||||
stream: &mut RWStreamWithLimit<'_, T>,
|
||||
)-> Result<IncomingPackageContent, String> {
|
||||
Ok(match (connection_state, protocol_id.to_rs()){
|
||||
#variants_match,
|
||||
(other_state, other_id) => {
|
||||
return Err(format!("Unrecognized protocol+state combination: {:?}/{}", other_state, other_id));
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("This macro is only supported for Enums")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ProtocolVariant {
|
||||
attr: ProtocolAttribute,
|
||||
ident: Ident,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct ProtocolAttribute {
|
||||
state: syn::ExprPath,
|
||||
packet_id: Lit,
|
||||
}
|
||||
impl Parse for ProtocolAttribute {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let state = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
let packet_id = input.parse()?;
|
||||
|
||||
Ok(ProtocolAttribute { state, packet_id })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user