use arrayvec::ArrayVec;
use nom::AsBytes;
use serde::ser::SerializeSeq;
use serde::{ser, Serialize, Serializer};
use std::io;
use uuid::Uuid;
use crate::chunks::{
TH_ANTIBOT, TH_AUTH_INIT, TH_AUTH_LOGIN, TH_AUTH_LOGOUT, TH_DDNETVER, TH_DDNETVER_OLD,
TH_JOINVER6, TH_JOINVER7, TH_LOAD_FAILURE, TH_LOAD_SUCCESS, TH_PLAYER_FINISH, TH_PLAYER_NAME,
TH_PLAYER_READY, TH_PLAYER_SWAP, TH_PLAYER_TEAM, TH_REJOINVER6, TH_SAVE_FAILURE,
TH_SAVE_SUCCESS, TH_TEAM_FINISH, TH_TEAM_PRACTICE, TH_TEST,
};
use crate::{error, Chunk};
use error::{Error, Result};
struct Packer<W: io::Write> {
writer: W,
}
impl<W: io::Write> Packer<W> {
fn new(writer: W) -> Self {
Self { writer }
}
}
pub fn serialize_into<W, T>(writer: W, value: &T) -> Result<()>
where
W: io::Write,
T: Serialize,
{
let mut p = Packer::new(writer);
value.serialize(&mut p)
}
pub struct ThWriter<W: io::Write> {
packer: Packer<W>,
}
pub fn null_terminator<T, S>(bytes: &T, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
T: ?Sized + Serialize,
S: Serializer,
{
let mut s = serializer.serialize_seq(None)?;
s.serialize_element(bytes)?;
s.serialize_element(&[0u8])?;
s.end()
}
pub fn inner_null_terminator<T, S>(
bytes_slice: &[T],
serializer: S,
) -> std::result::Result<S::Ok, S::Error>
where
T: Serialize,
S: Serializer,
{
let mut s = serializer.serialize_seq(None)?;
for bytes in bytes_slice {
s.serialize_element(bytes)?;
s.serialize_element(&[0u8])?;
}
s.end()
}
impl<W: io::Write> ThWriter<W> {
pub fn new(mut writer: W, header: &str) -> Result<ThWriter<W>> {
writer.write_all(Uuid::from_u128(0x699db17b_8efb_34ff_b1d8_da6f60c15dd1).as_bytes())?;
writer.write_all(header.as_bytes())?;
writer.write_all(b"\0")?;
Ok(ThWriter {
packer: Packer::new(writer),
})
}
}
impl<W: io::Write> ThWriter<W> {
pub fn add_chunk(&mut self, c: &Chunk) -> Result<()> {
c.serialize(&mut self.packer)
}
}
fn serialize_small_extra<T>(value: &T) -> Result<ArrayVec<u8, 64>>
where
T: Serialize,
{
let mut serializer = Packer {
writer: ArrayVec::<u8, 64>::new(),
};
value.serialize(&mut serializer)?;
Ok(serializer.writer)
}
fn serialize_large_extra<T>(value: &T) -> Result<ArrayVec<u8, 2048>>
where
T: Serialize,
{
let mut serializer = Packer {
writer: ArrayVec::<u8, 2048>::new(),
};
value.serialize(&mut serializer)?;
Ok(serializer.writer)
}
impl<'a, W> ser::Serializer for &'a mut Packer<W>
where
W: io::Write,
{
type Ok = ();
type Error = Error;
type SerializeSeq = Self;
type SerializeTuple = Self;
type SerializeTupleStruct = Self;
type SerializeTupleVariant = Self;
type SerializeMap = Self;
type SerializeStruct = Self;
type SerializeStructVariant = Self;
fn serialize_bool(self, _v: bool) -> Result<Self::Ok> {
todo!()
}
fn serialize_i8(self, _v: i8) -> Result<Self::Ok> {
todo!()
}
fn serialize_i16(self, _v: i16) -> Result<Self::Ok> {
todo!()
}
fn serialize_i32(self, int: i32) -> Result<Self::Ok> {
let sign = if int < 0 { 1 } else { 0 };
let mut int = (int ^ -sign) as u32;
let mut next = (int & 0b0011_1111) as u8;
int >>= 6;
if int != 0 {
next |= 0b1000_0000;
}
if sign != 0 {
next |= 0b0100_0000;
}
self.writer.write_all(&[next])?;
while int != 0 {
let mut next = (int & 0b0111_1111) as u8;
int >>= 7;
if int != 0 {
next |= 0b1000_0000;
}
self.writer.write_all(&[next])?;
}
Ok(())
}
fn serialize_i64(self, _v: i64) -> Result<Self::Ok> {
todo!()
}
fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
self.writer.write_all(&[v])?;
Ok(())
}
fn serialize_u16(self, _v: u16) -> Result<Self::Ok> {
todo!()
}
fn serialize_u32(self, _v: u32) -> Result<Self::Ok> {
todo!()
}
fn serialize_u64(self, _v: u64) -> Result<Self::Ok> {
todo!()
}
fn serialize_f32(self, _v: f32) -> Result<Self::Ok> {
todo!()
}
fn serialize_f64(self, _v: f64) -> Result<Self::Ok> {
todo!()
}
fn serialize_char(self, _v: char) -> Result<Self::Ok> {
todo!()
}
fn serialize_str(self, v: &str) -> Result<Self::Ok> {
self.writer.write_all(v.as_bytes())?;
self.writer.write_all(b"\0")?;
Ok(())
}
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok> {
self.writer.write_all(v)?;
Ok(())
}
fn serialize_none(self) -> Result<Self::Ok> {
todo!()
}
fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok>
where
T: Serialize,
{
todo!()
}
fn serialize_unit(self) -> Result<Self::Ok> {
Ok(())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
todo!()
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
) -> Result<Self::Ok> {
todo!()
}
fn serialize_newtype_struct<T: ?Sized>(
self,
_name: &'static str,
_value: &T,
) -> Result<Self::Ok>
where
T: Serialize,
{
todo!()
}
fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<Self::Ok>
where
T: Serialize,
{
todo!()
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
Ok(self)
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
Ok(self)
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct> {
todo!()
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant> {
todo!()
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
todo!()
}
fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
Ok(self)
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant> {
todo!()
}
}
impl<'a, W: io::Write> ser::SerializeSeq for &'a mut Packer<W> {
type Ok = ();
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<()> {
Ok(())
}
}
impl<'a, W: io::Write> ser::SerializeTuple for &'a mut Packer<W> {
type Ok = ();
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<()> {
Ok(())
}
}
impl<'a, W: io::Write> ser::SerializeTupleStruct for &'a mut Packer<W> {
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, _value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
todo!()
}
fn end(self) -> Result<()> {
todo!()
}
}
impl<'a, W: io::Write> ser::SerializeTupleVariant for &'a mut Packer<W> {
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, _value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
todo!()
}
fn end(self) -> Result<()> {
todo!()
}
}
impl<'a, W: io::Write> ser::SerializeMap for &'a mut Packer<W> {
type Ok = ();
type Error = Error;
fn serialize_key<T>(&mut self, _key: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
todo!()
}
fn serialize_value<T>(&mut self, _value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
todo!()
}
fn end(self) -> Result<()> {
todo!()
}
}
impl<'a, W: io::Write> ser::SerializeStruct for &'a mut Packer<W> {
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, _key: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<()> {
Ok(())
}
}
impl<'a, W: io::Write> ser::SerializeStructVariant for &'a mut Packer<W> {
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, _key: &'static str, _value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
todo!()
}
fn end(self) -> Result<()> {
todo!()
}
}
fn serialize_chunk_normal<S, T>(
serializer: S,
id: i32,
value: &T,
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
T: Serialize,
{
assert!(id < 0);
let mut seq = serializer.serialize_seq(None)?;
seq.serialize_element::<i32>(&id)?;
seq.serialize_element(value)?;
seq.end()
}
fn serialize_chunk_ex_small<S, T>(
serializer: S,
uuid: Uuid,
value: &T,
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
T: Serialize,
{
let mut seq = serializer.serialize_seq(None)?;
seq.serialize_element::<i32>(&-11)?;
seq.serialize_element(&uuid.as_bytes())?;
let ex = serialize_small_extra(value).map_err(ser::Error::custom)?;
seq.serialize_element(&(ex.len() as i32))?; seq.serialize_element(&ex.as_bytes())?;
seq.end()
}
fn serialize_chunk_ex_large<S, T>(
serializer: S,
uuid: Uuid,
value: &T,
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
T: Serialize,
{
let mut seq = serializer.serialize_seq(None)?;
seq.serialize_element::<i32>(&-11)?;
seq.serialize_element(uuid.as_bytes())?;
let ex = serialize_large_extra(value).map_err(ser::Error::custom)?;
seq.serialize_element(&(ex.len() as i32))?; seq.serialize_element(&ex.as_bytes())?;
seq.end()
}
impl<'a> Serialize for crate::chunks::Chunk<'a> {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
Chunk::PlayerDiff(c) => {
assert!(c.cid >= 0);
c.serialize(serializer)
}
Chunk::Eos => serializer.serialize_i32(-1),
Chunk::TickSkip(c) => serialize_chunk_normal(serializer, -2, c),
Chunk::PlayerNew(c) => serialize_chunk_normal(serializer, -3, c),
Chunk::PlayerOld(c) => serialize_chunk_normal(serializer, -4, c),
Chunk::InputDiff(c) => serialize_chunk_normal(serializer, -5, c),
Chunk::InputNew(c) => serialize_chunk_normal(serializer, -6, c),
Chunk::NetMessage(c) => serialize_chunk_normal(serializer, -7, c),
Chunk::Join(c) => serialize_chunk_normal(serializer, -8, c),
Chunk::Drop(c) => serialize_chunk_normal(serializer, -9, c),
Chunk::ConsoleCommand(c) => serialize_chunk_normal(serializer, -10, c),
Chunk::UnknownEx(c) => {
let mut seq = serializer.serialize_seq(None)?;
seq.serialize_element::<i32>(&-11)?;
seq.serialize_element(c)?;
seq.end()
}
Chunk::Test => serialize_chunk_ex_small(serializer, TH_TEST, &()),
Chunk::DdnetVersionOld(c) => serialize_chunk_ex_small(serializer, TH_DDNETVER_OLD, c),
Chunk::DdnetVersion(c) => serialize_chunk_ex_large(serializer, TH_DDNETVER, c),
Chunk::AuthInit(c) => serialize_chunk_ex_small(serializer, TH_AUTH_INIT, c),
Chunk::AuthLogin(c) => serialize_chunk_ex_small(serializer, TH_AUTH_LOGIN, c),
Chunk::AuthLogout(c) => serialize_chunk_ex_small(serializer, TH_AUTH_LOGOUT, c),
Chunk::JoinVer6(c) => serialize_chunk_ex_small(serializer, TH_JOINVER6, c),
Chunk::JoinVer7(c) => serialize_chunk_ex_small(serializer, TH_JOINVER7, c),
Chunk::RejoinVer6(c) => serialize_chunk_ex_small(serializer, TH_REJOINVER6, c),
Chunk::TeamSaveSuccess(c) => serialize_chunk_ex_large(serializer, TH_SAVE_SUCCESS, c),
Chunk::TeamSaveFailure(c) => serialize_chunk_ex_small(serializer, TH_SAVE_FAILURE, c),
Chunk::TeamLoadSuccess(c) => serialize_chunk_ex_large(serializer, TH_LOAD_SUCCESS, c),
Chunk::TeamLoadFailure(c) => serialize_chunk_ex_small(serializer, TH_LOAD_FAILURE, c),
Chunk::PlayerTeam(c) => serialize_chunk_ex_small(serializer, TH_PLAYER_TEAM, c),
Chunk::TeamPractice(c) => serialize_chunk_ex_small(serializer, TH_TEAM_PRACTICE, c),
Chunk::PlayerReady(c) => serialize_chunk_ex_small(serializer, TH_PLAYER_READY, c),
Chunk::PlayerSwap(c) => serialize_chunk_ex_small(serializer, TH_PLAYER_SWAP, c),
Chunk::Antibot(c) => serialize_chunk_ex_small(serializer, TH_ANTIBOT, c),
Chunk::PlayerName(c) => serialize_chunk_ex_small(serializer, TH_PLAYER_NAME, c),
Chunk::PlayerFinish(c) => serialize_chunk_ex_small(serializer, TH_PLAYER_FINISH, c),
Chunk::TeamFinish(c) => serialize_chunk_ex_small(serializer, TH_TEAM_FINISH, c),
}
}
}