GeezerVison is showing github.com — changes · Defman/feather-protocol@a4555e6
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: codegen/src/generation.rs +26-6Lines changed: 26 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -175,7 +175,8 @@ pub struct PacketGenerator; | 175 | 175 |
| 176 | 176 | impl PacketGenerator { | 177 | 177 | pub fn generate(identifier: &PacketIdentifier, packet: &Packet) -> (TokenStream, Ident) { | 178 | | - let ident = Ident::new(&format!("{}_packet", *packet.name), Span::call_site()); | | 178 | + use heck::SnakeCase; | | 179 | + let ident = Ident::new(&format!("{}_packet", &*packet.name.to_snake_case()), Span::call_site()); | 179 | 180 | let (custom_type, custom_type_ident) = CustomTypeGenerator::generate("packet", &packet.custom_type); | 180 | 181 |
| 181 | 182 | let id_lit = LitInt::new(&identifier.id().to_string(), Span::call_site()); | @@ -245,6 +246,11 @@ impl CustomTypeGenerator { | 245 | 246 | CustomType::Enum { variant, variants } => Self::generate_enum(name, variants), | 246 | 247 | CustomType::Unit => Self::generate_unit(name), | 247 | 248 | CustomType::BitField(_) => (quote! {}, Self::ident(name)), | | 249 | + CustomType::BitFlags { .. } => (quote! { | | 250 | + bitflags! { | | 251 | + | | 252 | + } | | 253 | + }, Self::ident(name)) | 248 | 254 | } | 249 | 255 | } | 250 | 256 |
| @@ -261,8 +267,13 @@ impl CustomTypeGenerator { | 261 | 267 | .iter() | 262 | 268 | .filter(|(_, ty)| !matches!(ty, Type::Key(_))) | 263 | 269 | .map(|(name, ty)| { | | 270 | + let name = name.to_snake_case(); | | 271 | + let name = match &name { | | 272 | + "type" => "kind".to_owned(), | | 273 | + name => name, | | 274 | + }; | 264 | 275 | ( | 265 | | - Ident::new(&name.to_snake_case(), Span::call_site()), | | 276 | + Ident::new(&name, Span::call_site()), | 266 | 277 | TypeGenerator::generate(ty), | 267 | 278 | ) | 268 | 279 | }) | @@ -348,23 +359,32 @@ impl TypeGenerator { | 348 | 359 | Type::I32 => (quote! {}, quote! { i32 }), | 349 | 360 | Type::U64 => (quote! {}, quote! { u64 }), | 350 | 361 | Type::I64 => (quote! {}, quote! { i64 }), | | 362 | + Type::F32 => (quote! {}, quote! { f32 }), | | 363 | + Type::F64 => (quote! {}, quote! { f64 }), | 351 | 364 | Type::VarInt => (quote! {}, quote! { VarInt }), | | 365 | + Type::VarLong => (quote! {}, quote! { VarLong }), | 352 | 366 | Type::Uuid => (quote! {}, quote! { uuid::Uuid }), | 353 | 367 | Type::String(_) => (quote! {}, quote! { String }), | 354 | 368 | Type::Nbt => (quote! {}, quote! { () }), | 355 | 369 | Type::Array { kind, .. } => { | 356 | | - let (tokens, ident) = TypeGenerator::generate(kind); | | 370 | + let (tokens, ident) = TypeGenerator::generate(kind.as_ref()); | 357 | 371 | (tokens, quote! { Vec<#ident> }) | 358 | 372 | } | 359 | 373 | Type::Option(inner) => { | 360 | | - let (tokens, ident) = TypeGenerator::generate(inner); | | 374 | + let (tokens, ident) = TypeGenerator::generate(inner.as_ref()); | 361 | 375 | (tokens, quote! { Option<#ident> }) | 362 | 376 | } | 363 | 377 | Type::CustomType(name, custom_type) => { | 364 | | - let (tokens, ident) = CustomTypeGenerator::generate(name, custom_type); | | 378 | + let (tokens, ident) = CustomTypeGenerator::generate(name.as_ref(), &custom_type); | 365 | 379 | (quote! { #tokens }, quote! { #ident }) | 366 | 380 | } | 367 | | - Type::Key(_) => (quote! { () }, quote! {}), | | 381 | + Type::Constant(_) => (quote! { }, quote! {}), | | 382 | + Type::Key(_) => (quote! { }, quote! {}), | | 383 | + Type::Shared(name) => { | | 384 | + use heck::SnakeCase; | | 385 | + let name = Ident::new(&name.to_snake_case(), Span::call_site()); | | 386 | + (quote! {}, quote! { shared::#name }) | | 387 | + } | 368 | 388 | } | 369 | 389 | } | 370 | 390 | } |
Collapse file Copy file name to clipboard +6-12Lines changed: 6 additions & 12 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | use anyhow::Result; | 2 | | -use feather_protocol_spec::{PacketIdentifier, PacketDirection, PacketStage, Packet}; | 3 | | -use feather_protocol_codegen::PacketGenerator; | | 2 | +use feather_protocol_spec::Protocol; | | 3 | +use feather_protocol_codegen::ProtocolGenerator; | 4 | 4 |
| 5 | 5 | #[test] | 6 | 6 | fn player_info_packet() -> Result<()> { | 7 | | - let packet_bytes = include_bytes!("player_info_packet.ron"); | | 7 | + let packet_bytes = include_bytes!("../../protocols/1.15.2.ron"); | 8 | 8 |
| 9 | | - let packet_de: Packet = ron::de::from_bytes(packet_bytes)?; | 10 | | - | 11 | | - let packet_identifier = PacketIdentifier { | 12 | | - direction: PacketDirection::Client, | 13 | | - stage: PacketStage::Play, | 14 | | - id: 0.into(), | 15 | | - }; | | 9 | + let protocol_de: Protocol = ron::de::from_bytes(packet_bytes)?; | 16 | 10 |
| 17 | | - let (packet_tokens, _packet_ident) = PacketGenerator::generate(&packet_identifier, &packet_de); | | 11 | + let protocol = ProtocolGenerator::generate(protocol_de); | 18 | 12 |
| 19 | | - println!("{}", packet_tokens); | | 13 | + println!("{}", protocol); | 20 | 14 |
| 21 | 15 | Ok(()) | 22 | 16 | } |
Collapse file Copy file name to clipboardExpand all lines: protocols/1.15.2.ron +3-3Lines changed: 3 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 767 | 767 | }) | 768 | 768 | ), | 769 | 769 | (Server, Play, 0x13): ( | 770 | | - name: "player rotation", | | 770 | + name: "player_rotation", | 771 | 771 | custom_type: Struct({ | 772 | 772 | "yaw": F32, | 773 | 773 | "pitch": F32, | | 781 | 781 | }) | 782 | 782 | ), | 783 | 783 | (Server, Play, 0x15): ( | 784 | | - name: "vehicle Move", | | 784 | + name: "vehicle_move", | 785 | 785 | custom_type: Struct({ | 786 | 786 | "x": F64, | 787 | 787 | "y": F64, | | 1105 | 1105 | }) | 1106 | 1106 | ), | 1107 | 1107 | (Server, Play, 0x2D): ( | 1108 | | - name: "use item", | | 1108 | + name: "use_item", | 1109 | 1109 | custom_type: Struct({ | 1110 | 1110 | "hand": Shared("hand") | 1111 | 1111 | }), | |
Collapse file Copy file name to clipboard +41Lines changed: 41 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +use crate::*; | | 2 | + | | 3 | +use anyhow::{bail, Result}; | | 4 | +use std::collections::BTreeMap; | | 5 | + | | 6 | +pub trait Validation { | | 7 | + fn validate(&self) -> Result<()>; | | 8 | +} | | 9 | + | | 10 | +impl Validation for Protocol { | | 11 | + fn validate(&self) -> Result<()> { | | 12 | + let mut packet_names = BTreeMap::new(); | | 13 | + let mut prev: Option<&PacketIdentifier> = None; | | 14 | + for (identifier, packet) in self.packets.iter() { | | 15 | + if let Some(prev_identifier) = prev { | | 16 | + if prev_identifier.direction() == identifier.direction() | | 17 | + && prev_identifier.stage() == identifier.stage() | | 18 | + && !(*prev_identifier.id() + 1 == *identifier.id()) { | | 19 | + println!("Skiped from {:#X?} to {:#X?}", prev_identifier, identifier); | | 20 | + } | | 21 | + } | | 22 | + prev = Some(identifier); | | 23 | + if let Some(old_identifier) = packet_names.insert( | | 24 | + ( | | 25 | + identifier.direction(), | | 26 | + identifier.stage(), | | 27 | + packet.name.clone(), | | 28 | + ), | | 29 | + identifier, | | 30 | + ) { | | 31 | + bail!( | | 32 | + "The packet name \"{}\" for {:#X?} is already used by {:#X?}.", | | 33 | + *packet.name, | | 34 | + identifier, | | 35 | + old_identifier | | 36 | + ); | | 37 | + } | | 38 | + } | | 39 | + Ok(()) | | 40 | + } | | 41 | +} |
Collapse file Copy file name to clipboard +80Lines changed: 80 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +use std::marker::PhantomData; | | 2 | +use bytes::{Buf, BufMut}; | | 3 | +use crate::packets::{direction, stage, Protocol}; | | 4 | + | | 5 | +pub trait Encoder<P, D, S> | | 6 | +where | | 7 | + P: Protocol, | | 8 | + D: direction::Direction, | | 9 | + S: stage::Stage, | | 10 | +{ | | 11 | + pub fn encode(packet: impl Packet<D, S>) -> impl BufMut; | | 12 | +} | | 13 | + | | 14 | +pub trait Decoder<P, D, S> | | 15 | +where | | 16 | + P: Protocol, | | 17 | + D: direction::Direction, | | 18 | + S: stage::Stage, | | 19 | +{ | | 20 | + pub fn decode(buf: impl Buf) -> impl Packet; | | 21 | +} | | 22 | + | | 23 | +struct FeatherCodec<P: Protocol>; | | 24 | + | | 25 | +macro_rules! encoder { | | 26 | + ($direction:path, $stage:path) => { | | 27 | + impl<P: Protocol> Encoder<P, $direction, $stage> for FeatherCodec<P> { | | 28 | + fn encode(packet: impl Packet<D, S>) -> impl BufMut { | | 29 | + unimplemented!() | | 30 | + } | | 31 | + } | | 32 | + }; | | 33 | +} | | 34 | + | | 35 | +encoder!(direction::Client, stage::Handshaking); | | 36 | +encoder!(direction::Client, stage::Status); | | 37 | +encoder!(direction::Client, stage::Login); | | 38 | +encoder!(direction::Client, stage::Play); | | 39 | + | | 40 | +encoder!(direction::Server, stage::Handshaking); | | 41 | +encoder!(direction::Server, stage::Status); | | 42 | +encoder!(direction::Server, stage::Login); | | 43 | +encoder!(direction::Server, stage::Play); | | 44 | + | | 45 | +macro_rules! decoder { | | 46 | + ($direction:path, $stage:path) => { | | 47 | + impl<P: Protocol> Decoder<P, $direction, $stage> for FeatherCodec<P> { | | 48 | + fn encode(packet: impl Packet<D, S>) -> impl BufMut { | | 49 | + unimplemented!() | | 50 | + } | | 51 | + } | | 52 | + }; | | 53 | +} | | 54 | + | | 55 | + | | 56 | +decoder!(direction::Client, stage::Handshaking); | | 57 | +decoder!(direction::Client, stage::Status); | | 58 | +decoder!(direction::Client, stage::Login); | | 59 | +decoder!(direction::Client, stage::Play); | | 60 | + | | 61 | +decoder!(direction::Server, stage::Handshaking); | | 62 | +decoder!(direction::Server, stage::Status); | | 63 | +decoder!(direction::Server, stage::Login); | | 64 | +decoder!(direction::Server, stage::Play); | | 65 | + | | 66 | + | | 67 | +#[cfg(test)] | | 68 | +mod tests { | | 69 | + use super::*; | | 70 | + | | 71 | + #[test] | | 72 | + fn encoder_test() { | | 73 | + // type codec = FeatherCodec<Protocol>; | | 74 | + // let packet = ...; | | 75 | + // let packet_encoded = codec::encode::<Client, Play>(packet); | | 76 | + // let packet_decoded = codec::decode::<Client, Play>(packet_encoded); | | 77 | + | | 78 | + // assert_eq!(packet_decoded, packet); | | 79 | + } | | 80 | +} |
|