diff --git a/.gitignore b/.gitignore index e420ee4..a81f421 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ target/* +lu_packets_derive/target* diff --git a/Cargo.lock b/Cargo.lock index 2e10ab6..e376752 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,16 @@ name = "lu_packets" version = "0.1.0" dependencies = [ "endio 0.2.0 (git+https://github.com/lcdr/endio?rev=cb5020f6749a301ae925592f9ad1920919894ddb)", + "lu_packets_derive 0.1.0", +] + +[[package]] +name = "lu_packets_derive" +version = "0.1.0" +dependencies = [ + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e7b3e3d..bc6fde2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,4 @@ repository = "https://github.com/lcdr/lu_packets/" [dependencies] endio = { git = "https://github.com/lcdr/endio", rev = "cb5020f6749a301ae925592f9ad1920919894ddb" } +lu_packets_derive = { path = "lu_packets_derive" } diff --git a/lu_packets_derive/Cargo.lock b/lu_packets_derive/Cargo.lock new file mode 100644 index 0000000..c5d8f2d --- /dev/null +++ b/lu_packets_derive/Cargo.lock @@ -0,0 +1,45 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "lu_packets_derive" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/lu_packets_derive/Cargo.toml b/lu_packets_derive/Cargo.toml new file mode 100644 index 0000000..536f0f8 --- /dev/null +++ b/lu_packets_derive/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "lu_packets_derive" +version = "0.1.0" +authors = ["lcdr"] +edition = "2018" +license = "AGPL-3.0-or-later" +repository = "https://github.com/lcdr/lu_packets/" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0" +quote = "1.0" +syn = "1.0" diff --git a/lu_packets_derive/src/lib.rs b/lu_packets_derive/src/lib.rs new file mode 100644 index 0000000..5ccd4ad --- /dev/null +++ b/lu_packets_derive/src/lib.rs @@ -0,0 +1,42 @@ +use quote::quote; +use syn::{parse_macro_input, Data, DeriveInput, Fields}; + +#[proc_macro_derive(FromVariants)] +pub fn derive_deserialize(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = parse_macro_input!(input as DeriveInput); + + let data = match &input.data { + Data::Enum(data) => data, + _ => panic!("only enums are supported"), + }; + + let name = &input.ident; + + let mut impls = vec![]; + for v in &data.variants { + let variant = &v.ident; + let fields = match &v.fields { + Fields::Named(_) => panic!("use a tuple or unit variant"), + Fields::Unit => { continue } + Fields::Unnamed(fields) => fields, + }; + + if fields.unnamed.len() != 1 { + panic!("use exactly one tuple argument"); + } + let first = fields.unnamed.first().unwrap(); + let variant_ty = &first.ty; + + let impl_ = quote! { + impl ::std::convert::From<#variant_ty> for Message { + fn from(msg: #variant_ty) -> Self { + #name::#variant(msg).into() + } + } + }; + impls.push(impl_); + } + (quote! { + #(#impls)* + }).into() +} diff --git a/src/auth/client.rs b/src/auth/client.rs index 1385a80..3de75cc 100644 --- a/src/auth/client.rs +++ b/src/auth/client.rs @@ -2,50 +2,26 @@ use std::io::Result as Res; use endio::{LEWrite, Serialize}; use endio::LittleEndian as LE; +use lu_packets_derive::FromVariants; -use crate::common::{LuStr33, LuWStr33, ServiceId}; -use crate::general::client::{GeneralMessage, Handshake}; +use crate::common::{LuStr33, LuWStr33}; +pub type LuMessage = crate::general::client::LuMessage; pub type Message = crate::raknet::client::Message; -impl From for Message { - fn from(msg: GeneralMessage) -> Self { - LuMessage::General(msg).into() - } -} - -impl From for Message { - fn from(msg: Handshake) -> Self { - GeneralMessage::Handshake(msg).into() - } -} - -#[derive(Debug, Serialize)] -#[repr(u16)] -pub enum LuMessage { - General(GeneralMessage) = ServiceId::General as u16, - Client(ClientMessage) = ServiceId::Client as u16, -} - -impl From for Message { - fn from(msg: LuMessage) -> Self { - Message::UserMessage(msg) - } -} - -#[derive(Debug)] -#[non_exhaustive] -#[repr(u32)] -pub enum ClientMessage { - LoginResponse(LoginResponse), -} - impl From for Message { fn from(msg: ClientMessage) -> Self { LuMessage::Client(msg).into() } } +#[derive(Debug, FromVariants)] +#[non_exhaustive] +#[repr(u32)] +pub enum ClientMessage { + LoginResponse(LoginResponse), +} + impl<'a, W: LEWrite> Serialize for &'a ClientMessage where u8: Serialize, u32: Serialize, @@ -75,12 +51,6 @@ pub enum LoginResponse { InvalidUsernamePassword = 6, } -impl From for Message { - fn from(msg: LoginResponse) -> Self { - ClientMessage::LoginResponse(msg).into() - } -} - impl<'a, W: LEWrite> Serialize for &'a LoginResponse where u8: Serialize, u16: Serialize, diff --git a/src/general/client.rs b/src/general/client.rs index 20f0f0e..2c174c3 100644 --- a/src/general/client.rs +++ b/src/general/client.rs @@ -5,6 +5,27 @@ use endio::LittleEndian as LE; use crate::common::ServiceId; +pub type Message = crate::raknet::client::Message>; + +#[derive(Debug, Serialize)] +#[repr(u16)] +pub enum LuMessage { + General(GeneralMessage) = ServiceId::General as u16, + Client(C) = ServiceId::Client as u16, +} + +impl From> for Message { + fn from(msg: LuMessage) -> Self { + Message::UserMessage(msg) + } +} + +impl From for Message { + fn from(msg: GeneralMessage) -> Self { + LuMessage::General(msg).into() + } +} + #[derive(Debug)] #[non_exhaustive] #[repr(u32)] @@ -13,6 +34,18 @@ pub enum GeneralMessage { DisconnectNotify(DisconnectNotify), } +impl From for Message { + fn from(msg: Handshake) -> Self { + GeneralMessage::Handshake(msg).into() + } +} + +impl From for Message { + fn from(msg: DisconnectNotify) -> Self { + GeneralMessage::DisconnectNotify(msg).into() + } +} + impl<'a, W: LEWrite> Serialize for &'a GeneralMessage where u8: Serialize, u32: Serialize, diff --git a/src/world/client.rs b/src/world/client.rs index 855ac93..1f86f13 100644 --- a/src/world/client.rs +++ b/src/world/client.rs @@ -2,44 +2,20 @@ use std::io::Result as Res; use endio::{LEWrite, Serialize}; use endio::LittleEndian as LE; +use lu_packets_derive::FromVariants; -use crate::common::{ObjId, LuWStr33, ServiceId, ZoneId}; -use crate::general::client::{DisconnectNotify, GeneralMessage, Handshake}; +use crate::common::{ObjId, LuWStr33, ZoneId}; +pub type LuMessage = crate::general::client::LuMessage; pub type Message = crate::raknet::client::Message; -impl From for Message { - fn from(msg: GeneralMessage) -> Self { - LuMessage::General(msg).into() +impl From for Message { + fn from(msg: ClientMessage) -> Self { + LuMessage::Client(msg).into() } } -impl From for Message { - fn from(msg: Handshake) -> Self { - GeneralMessage::Handshake(msg).into() - } -} - -impl From for Message { - fn from(msg: DisconnectNotify) -> Self { - GeneralMessage::DisconnectNotify(msg).into() - } -} - -#[derive(Debug, Serialize)] -#[repr(u16)] -pub enum LuMessage { - General(GeneralMessage) = ServiceId::General as u16, - Client(ClientMessage) = ServiceId::Client as u16, -} - -impl From for Message { - fn from(msg: LuMessage) -> Self { - Message::UserMessage(msg) - } -} - -#[derive(Debug)] +#[derive(Debug, FromVariants)] #[non_exhaustive] #[repr(u32)] pub enum ClientMessage { @@ -48,12 +24,6 @@ pub enum ClientMessage { CharacterDeleteResponse(CharacterDeleteResponse) = 11, } -impl From for Message { - fn from(msg: ClientMessage) -> Self { - LuMessage::Client(msg).into() - } -} - impl<'a, W: LEWrite> Serialize for &'a ClientMessage where u8: Serialize, u32: Serialize, @@ -85,12 +55,6 @@ pub struct CharacterListResponse { pub chars: Vec, } -impl From for Message { - fn from(msg: CharacterListResponse) -> Self { - ClientMessage::CharacterListResponse(msg).into() - } -} - impl<'a, W: LEWrite> Serialize for &'a CharacterListResponse where u8: Serialize, &'a CharListChar: Serialize { @@ -170,19 +134,7 @@ pub enum CharacterCreateResponse { CustomNameInUse, } -impl From for Message { - fn from(msg: CharacterCreateResponse) -> Self { - ClientMessage::CharacterCreateResponse(msg).into() - } -} - #[derive(Debug, Serialize)] pub struct CharacterDeleteResponse { pub success: bool, } - -impl From for Message { - fn from(msg: CharacterDeleteResponse) -> Self { - ClientMessage::CharacterDeleteResponse(msg).into() - } -}