Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions lu_packets_derive/src/replica_serde.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
use syn::{parse_macro_input, parse_quote, Attribute, Data, DataEnum, DeriveInput, Field, Fields, Generics, Lit, LitInt, Meta, NestedMeta};
use syn::{
Attribute, Data, DataEnum, DeriveInput, Field, Fields, Lit, LitInt, Meta, NestedMeta,
parse_macro_input, parse_quote,
};

pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as DeriveInput);
Expand All @@ -10,14 +13,14 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
match &input.data {
Data::Struct(data) => {
deser_code = gen_deser_code_struct(&data.fields);
ser_code = gen_ser_code_struct(&data.fields, &name);
},
ser_code = gen_ser_code_struct(&data.fields, name);
}
Data::Enum(data) => {
let ty = get_enum_type(&input);
let pre_disc_padding = get_pre_disc_padding(&input);
let post_disc_padding = get_post_disc_padding(&input);
deser_code = gen_deser_code_enum(data, &name, &ty, &pre_disc_padding, &post_disc_padding);
ser_code = gen_ser_code_enum(data, &name, &ty, &pre_disc_padding, &post_disc_padding, &input.generics);
deser_code = gen_deser_code_enum(data, name, &ty, &pre_disc_padding, &post_disc_padding);
ser_code = gen_ser_code_enum(data, name, &ty, &pre_disc_padding, &post_disc_padding);
}
Data::Union(_) => unimplemented!(),
}
Expand Down Expand Up @@ -182,7 +185,7 @@ fn gen_ser_code_struct(fields: &Fields, name: &Ident) -> TokenStream {
}
}

fn gen_ser_code_enum(data: &DataEnum, name: &Ident, ty: &Ident, pre_disc_padding: &Option<LitInt>, post_disc_padding: &Option<LitInt>, generics: &Generics) -> TokenStream {
fn gen_ser_code_enum(data: &DataEnum, name: &Ident, ty: &Ident, pre_disc_padding: &Option<LitInt>, post_disc_padding: &Option<LitInt>) -> TokenStream {
let mut arms = vec![];
for f in &data.variants {
let ident = &f.ident;
Expand All @@ -194,7 +197,7 @@ fn gen_ser_code_enum(data: &DataEnum, name: &Ident, ty: &Ident, pre_disc_padding
let write_post_padding = gen_write_padding(post_disc_padding);
quote! {
#write_pre_padding
let disc = unsafe { *(self as *const #name #generics as *const #ty) };
let disc = unsafe { *::std::ptr::from_ref(self).cast::<#ty>() };
::endio::LEWrite::write(writer, disc)?;
#write_post_padding
match self {
Expand Down
24 changes: 15 additions & 9 deletions src/auth/client/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
//! Client-received auth messages.
use std::io::{Error, ErrorKind::InvalidData, Result as Res, Read};
use std::{
io::{Error, ErrorKind::InvalidData, Read, Result as Res},
ptr,
};

use endio::{LEWrite, LERead, Deserialize, Serialize};
use endio::LittleEndian as LE;
use lu_packets_derive::MessageFromVariants;
use lu_packets_derive::VariantTests;
use endio::{Deserialize, LERead, LEWrite, LittleEndian as LE, Serialize};
use lu_packets_derive::{MessageFromVariants, VariantTests};

use crate::common::{LuString3, LuString33, LuString37, LuVarWString, LuWString33, ServiceId};
use crate::general::client::{DisconnectNotify, Handshake, GeneralMessage};
use crate::world::server::Language;
use crate::{
common::{LuString3, LuString33, LuString37, LuVarWString, LuWString33, ServiceId},
general::client::{DisconnectNotify, GeneralMessage, Handshake},
world::server::Language,
};

/// All messages that can be received by a client from an auth server.
pub type Message = crate::raknet::client::Message<LuMessage>;
Expand Down Expand Up @@ -128,7 +131,10 @@ where
&'a LuVarWString<u16>: Serialize<LE, W>,
{
fn serialize(self, writer: &mut W) -> Res<()> {
let disc = unsafe { *(self as *const LoginResponse as *const u8) };
// SAFETY: Because `LoginResponse` is marked `repr(u8)`, its layout is a `repr(C)` `union`
// between `repr(C)` structs, each of which has the `u8` discriminant as its first
// field, so we can read the discriminant without offsetting the pointer.
let disc = unsafe { *ptr::from_ref(self).cast::<u8>() };
writer.write(disc)?;
match self {
LoginResponse::Ok { events, version, session_key, redirect_address, chat_server_address, cdn_key, cdn_ticket, language, country_code, just_upgraded_from_ftp, is_ftp, time_remaining_in_ftp, stamps } => {
Expand Down
28 changes: 16 additions & 12 deletions src/world/client/mod.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//! Client-received world messages.
use std::io::{Error, ErrorKind::InvalidData, Read, Write};
use std::io::Result as Res;
use std::{
io::{Error, ErrorKind::InvalidData, Read, Result as Res, Write},
ptr,
};

use endio::{Deserialize, LERead, LEWrite, Serialize};
use endio::LittleEndian as LE;
use endio::{Deserialize, LERead, LEWrite, LittleEndian as LE, Serialize};
use lu_packets_derive::{MessageFromVariants, VariantTests};

use crate::chat::ChatChannel;
use crate::chat::client::ChatMessage;
use crate::common::{ObjId, LuString33, LuWString33, LuWString42, LVec, ServiceId};
use crate::general::client::{DisconnectNotify, Handshake, GeneralMessage};
use super::{Lot, lnv::LuNameValue, Vector3, ZoneId};
use super::gm::client::SubjectGameMessage;
use super::{Lot, Vector3, ZoneId, gm::client::SubjectGameMessage, lnv::LuNameValue};
use crate::{
chat::{ChatChannel, client::ChatMessage},
common::{LVec, LuString33, LuWString33, LuWString42, ObjId, ServiceId},
general::client::{DisconnectNotify, GeneralMessage, Handshake},
};

/// All messages that can be received by a client from a world server.
pub type Message = crate::raknet::client::Message<LuMessage>;
Expand Down Expand Up @@ -378,9 +379,12 @@ impl<R: Read> Deserialize<LE, R> for AddFriendResponse {
}
}

impl<'a, W: Write> Serialize<LE, W> for &'a AddFriendResponse {
impl<W: Write> Serialize<LE, W> for &AddFriendResponse {
fn serialize(self, writer: &mut W) -> Res<()> {
let disc = unsafe { *(&self.response_type as *const AddFriendResponseType as *const u8) };
// SAFETY: Because `AddFriendResponseType` is marked `repr(u8)`, its layout is a `repr(C)` `union`
// between `repr(C)` structs, each of which has the `u8` discriminant as its first
// field, so we can read the discriminant without offsetting the pointer.
let disc = unsafe { *ptr::from_ref(self).cast::<u8>() };
LEWrite::write(writer, disc)?;
let mut is_online_x = &false;
let mut sender_id_x = &0;
Expand Down