Skip to content

Commit 9e1d8fb

Browse files
committed
chore: use macro to define packets
1 parent 343ecc6 commit 9e1d8fb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+369
-277
lines changed

Cargo.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
22
resolver = "2"
3-
members = ["crawlspace-server"]
3+
members = [ "crawlspace-macro","crawlspace"]
44

55
[profile.release-stripped]
66
inherits = "release"

crawlspace-macro/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "crawlspace-macro"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[lib]
7+
proc-macro = true
8+
9+
[dependencies]
10+
quote = "1.0.40"
11+
syn = "2.0.104"

crawlspace-macro/src/lib.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use proc_macro::{Span, TokenStream};
2+
use quote::quote;
3+
use syn::{parse_macro_input, DeriveInput, Ident, Lit};
4+
5+
#[proc_macro_derive(Packet, attributes(packet))]
6+
pub fn derive_packet(input: TokenStream) -> TokenStream {
7+
let input = parse_macro_input!(input as DeriveInput);
8+
9+
let syn::Data::Struct(_) = input.data else {
10+
panic!("Packet must be defined as a struct");
11+
};
12+
13+
let mut id = None;
14+
let mut state = None;
15+
let mut direction = None;
16+
17+
for attr in input.attrs {
18+
if !attr.path().is_ident("packet") {
19+
continue;
20+
}
21+
22+
attr.parse_nested_meta(|meta| {
23+
if meta.path.is_ident("id") {
24+
let lit = meta.value()?.parse()?;
25+
match lit {
26+
Lit::Str(i) => {
27+
id = Some(i);
28+
}
29+
_ => panic!("attribute value `id` must be a string"),
30+
}
31+
} else if meta.path.is_ident("state") {
32+
let lit = meta
33+
.value()
34+
.expect("no value for state")
35+
.parse()
36+
.expect("couldn't parse value for state");
37+
let Lit::Str(v) = lit else {
38+
panic!("unable to parse state as string");
39+
};
40+
state = Some(
41+
v.parse_with(syn::Path::parse_mod_style)
42+
.expect("couldn't parse state as path"),
43+
);
44+
} else if meta.path.is_ident("serverbound") {
45+
match direction {
46+
None => direction = Some("Serverbound"),
47+
Some(_) => {
48+
panic!("cannot have two directives of type `serverbound` or `clientbound`")
49+
}
50+
}
51+
} else if meta.path.is_ident("clientbound") {
52+
match direction {
53+
None => direction = Some("Clientbound"),
54+
Some(_) => {
55+
panic!("cannot have two directives of type `serverbound` or `clientbound`")
56+
}
57+
}
58+
} else {
59+
let Some(id) = meta.path.get_ident() else {
60+
panic!("unable to get ident for unrecognized directive");
61+
};
62+
panic!("unrecognized directive {}", id);
63+
}
64+
65+
Ok(())
66+
})
67+
.unwrap();
68+
}
69+
70+
let id = id.expect("id must be provided for packet");
71+
let state = state.expect("state must be provided for packet");
72+
let direction = Ident::new(
73+
direction.expect("direction must be provided for packet"),
74+
Span::call_site().into(),
75+
);
76+
77+
let name = input.ident;
78+
let where_clause = input.generics.where_clause.clone();
79+
let generics = input.generics;
80+
81+
quote! {
82+
impl #generics Packet for #name #generics #where_clause {
83+
fn id() -> &'static str {
84+
#id
85+
}
86+
87+
fn state() -> PacketState {
88+
#state
89+
}
90+
91+
fn direction() -> PacketDirection {
92+
PacketDirection::#direction
93+
}
94+
}
95+
}
96+
.into()
97+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ edition = "2021"
2222
license = "AGPL-3.0-or-later"
2323

2424
[dependencies]
25+
crawlspace-macro = { path = "../crawlspace-macro" }
26+
2527
aes = { version = "0.8.4", optional = true }
2628
bit-vec = "0.8.0"
2729
bitfield-struct = "0.9.2"
File renamed without changes.

0 commit comments

Comments
 (0)