use std::fmt::Debug;
use bitcode::encoding::{Fixed, Gamma};
use bytes::Bytes;
use crate::packet::packet::FRAGMENT_SIZE;
use crate::protocol::EventContext;
use crate::serialize::reader::ReadBuffer;
use crate::serialize::writer::WriteBuffer;
use crate::shared::replication::entity_map::MapEntities;
use crate::shared::tick_manager::Tick;
use crate::utils::named::Named;
use crate::utils::wrapping_id;
use crate::utils::wrapping_id::wrapping_id;
wrapping_id!(MessageId);
pub type FragmentIndex = u8;
#[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)]
pub(crate) struct MessageAck {
pub(crate) message_id: MessageId,
pub(crate) fragment_id: Option<FragmentIndex>,
}
#[derive(Debug, PartialEq)]
pub enum MessageContainer {
Single(SingleData),
Fragment(FragmentData),
}
impl From<FragmentData> for MessageContainer {
fn from(value: FragmentData) -> Self {
Self::Fragment(value)
}
}
impl From<SingleData> for MessageContainer {
fn from(value: SingleData) -> Self {
Self::Single(value)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SingleData {
pub id: Option<MessageId>,
pub tick: Option<Tick>,
pub bytes: Bytes,
}
impl SingleData {
pub fn new(id: Option<MessageId>, bytes: Bytes) -> Self {
Self {
id,
tick: None,
bytes,
}
}
pub(crate) fn encode(&self, writer: &mut impl WriteBuffer) -> anyhow::Result<usize> {
let num_bits_before = writer.num_bits_written();
writer.encode(&self.id, Fixed)?;
writer.encode(&self.tick, Fixed)?;
writer.encode(self.bytes.as_ref(), Fixed)?;
let num_bits_written = writer.num_bits_written() - num_bits_before;
Ok(num_bits_written)
}
pub(crate) fn decode(reader: &mut impl ReadBuffer) -> anyhow::Result<Self> {
let id = reader.decode::<Option<MessageId>>(Fixed)?;
let tick = reader.decode::<Option<Tick>>(Fixed)?;
let read_bytes = reader.decode::<Vec<u8>>(Fixed)?;
Ok(Self {
id,
tick,
bytes: Bytes::from(read_bytes),
})
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct FragmentData {
pub message_id: MessageId,
pub tick: Option<Tick>,
pub fragment_id: FragmentIndex,
pub num_fragments: FragmentIndex,
pub bytes: Bytes,
}
impl FragmentData {
pub(crate) fn encode(&self, writer: &mut impl WriteBuffer) -> anyhow::Result<usize> {
let num_bits_before = writer.num_bits_written();
writer.encode(&self.message_id, Fixed)?;
writer.encode(&self.tick, Fixed)?;
writer.encode(&self.fragment_id, Gamma)?;
writer.encode(&self.num_fragments, Gamma)?;
if self.is_last_fragment() {
writer.encode(self.bytes.as_ref(), Fixed)?;
} else {
let bytes_array: [u8; FRAGMENT_SIZE] = self.bytes.as_ref().try_into().unwrap();
writer.encode(&bytes_array, Fixed)?;
}
let num_bits_written = writer.num_bits_written() - num_bits_before;
Ok(num_bits_written)
}
pub(crate) fn decode(reader: &mut impl ReadBuffer) -> anyhow::Result<Self>
where
Self: Sized,
{
let message_id = reader.decode::<MessageId>(Fixed)?;
let tick = reader.decode::<Option<Tick>>(Fixed)?;
let fragment_id = reader.decode::<FragmentIndex>(Gamma)?;
let num_fragments = reader.decode::<FragmentIndex>(Gamma)?;
let bytes = if fragment_id == num_fragments - 1 {
let read_bytes = reader.decode::<Vec<u8>>(Fixed)?;
Bytes::from(read_bytes)
} else {
let read_bytes = reader.decode::<[u8; FRAGMENT_SIZE]>(Fixed)?;
let bytes_vec: Vec<u8> = read_bytes.to_vec();
Bytes::from(bytes_vec)
};
Ok(Self {
message_id,
tick,
fragment_id,
num_fragments,
bytes,
})
}
pub(crate) fn is_last_fragment(&self) -> bool {
self.fragment_id == self.num_fragments - 1
}
}
impl MessageContainer {
pub(crate) fn message_id(&self) -> Option<MessageId> {
match &self {
MessageContainer::Single(data) => data.id,
MessageContainer::Fragment(data) => Some(data.message_id),
}
}
pub(crate) fn encode(&self, writer: &mut impl WriteBuffer) -> anyhow::Result<usize> {
match &self {
MessageContainer::Single(data) => data.encode(writer),
MessageContainer::Fragment(data) => data.encode(writer),
}
}
pub fn set_id(&mut self, id: MessageId) {
match self {
MessageContainer::Single(data) => data.id = Some(id),
MessageContainer::Fragment(data) => data.message_id = id,
};
}
pub fn set_tick(&mut self, tick: Tick) {
match self {
MessageContainer::Single(data) => {
if data.tick.is_none() {
data.tick = Some(tick);
}
}
MessageContainer::Fragment(data) => {
if data.tick.is_none() {
data.tick = Some(tick);
}
}
};
}
pub fn bytes(&self) -> Bytes {
match self {
MessageContainer::Single(data) => data.bytes.clone(),
MessageContainer::Fragment(data) => data.bytes.clone(),
}
}
}
pub trait Message: EventContext + Named + MapEntities {}
#[cfg(test)]
mod tests {
use crate::_reexport::{ReadWordBuffer, WriteWordBuffer};
use super::*;
#[test]
fn test_serde_single_data() {
let data = SingleData::new(Some(MessageId(1)), vec![9, 3].into());
let mut writer = WriteWordBuffer::with_capacity(10);
let _a = data.encode(&mut writer).unwrap();
let bytes = writer.finish_write();
let mut reader = ReadWordBuffer::start_read(bytes);
let decoded = SingleData::decode(&mut reader).unwrap();
dbg!(&bytes);
assert_eq!(decoded, data);
dbg!(&writer.num_bits_written());
}
#[test]
fn test_serde_fragment_data() {
let bytes = Bytes::from(vec![0; 10]);
let data = FragmentData {
message_id: MessageId(0),
tick: None,
fragment_id: 2,
num_fragments: 3,
bytes: bytes.clone(),
};
let mut writer = WriteWordBuffer::with_capacity(10);
let _a = data.encode(&mut writer).unwrap();
let bytes = writer.finish_write();
let mut reader = ReadWordBuffer::start_read(bytes);
let decoded = FragmentData::decode(&mut reader).unwrap();
dbg!(&bytes);
assert_eq!(decoded, data);
dbg!(&writer.num_bits_written());
}
}