use alloc::slice;
use bevy::prelude::*;
use bytes::Buf;
use postcard::{
Deserializer, Serializer, de_flavors::Flavor as DeFlavor, ser_flavors::Flavor as SerFlavor,
};
use serde::{Deserialize, Serialize};
use crate::compact_entity;
pub fn to_extend_mut<T: Serialize + ?Sized, W: Extend<u8>>(
value: &T,
writer: &mut W,
) -> postcard::Result<()> {
postcard::serialize_with_flavor(value, ExtendMutFlavor::new(writer))
}
pub fn entity_to_extend_mut<W: Extend<u8>>(
entity: &Entity,
writer: &mut W,
) -> postcard::Result<()> {
let mut serializer = Serializer {
output: ExtendMutFlavor::new(writer),
};
compact_entity::serialize(entity, &mut serializer)
}
pub struct ExtendMutFlavor<'a, T: Extend<u8>> {
bytes: &'a mut T,
}
impl<'a, T: Extend<u8>> ExtendMutFlavor<'a, T> {
pub fn new(bytes: &'a mut T) -> Self {
Self { bytes }
}
}
impl<T: Extend<u8>> SerFlavor for ExtendMutFlavor<'_, T> {
type Output = ();
fn try_push(&mut self, data: u8) -> postcard::Result<()> {
self.bytes.extend([data]);
Ok(())
}
fn try_extend(&mut self, data: &[u8]) -> postcard::Result<()> {
self.bytes.extend(data.iter().copied());
Ok(())
}
fn finalize(self) -> postcard::Result<Self::Output> {
Ok(())
}
}
pub fn from_buf<'de, T: Deserialize<'de>, B: Buf>(buf: &'de mut B) -> postcard::Result<T> {
let mut deserializer = Deserializer::from_flavor(BufFlavor::new(buf));
T::deserialize(&mut deserializer)
}
pub fn entity_from_buf<B: Buf>(buf: &mut B) -> postcard::Result<Entity> {
let mut deserializer = Deserializer::from_flavor(BufFlavor::new(buf));
compact_entity::deserialize(&mut deserializer)
}
pub struct BufFlavor<'a, T: Buf> {
buf: &'a mut T,
}
impl<'a, T: Buf> BufFlavor<'a, T> {
pub fn new(buf: &'a mut T) -> Self {
Self { buf }
}
}
impl<'a, T: Buf> DeFlavor<'a> for BufFlavor<'a, T> {
type Remainder = ();
type Source = &'a [u8];
fn pop(&mut self) -> postcard::Result<u8> {
self.buf
.try_get_u8()
.map_err(|_| postcard::Error::DeserializeUnexpectedEnd)
}
fn size_hint(&self) -> Option<usize> {
Some(self.buf.remaining())
}
fn try_take_n(&mut self, ct: usize) -> postcard::Result<&'a [u8]> {
if self.buf.remaining() < ct {
return Err(postcard::Error::DeserializeUnexpectedEnd);
}
let buf = unsafe { slice::from_raw_parts(self.buf.chunk().as_ptr(), ct) };
self.buf.advance(ct);
Ok(buf)
}
fn finalize(self) -> postcard::Result<Self::Remainder> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use bevy::ecs::entity::{EntityGeneration, EntityIndex};
use super::*;
#[test]
fn entity_without_generation() {
let expected_entity = Entity::from_raw_u32(1).unwrap();
let mut buffer = Vec::new();
entity_to_extend_mut(&expected_entity, &mut buffer).unwrap();
assert_eq!(buffer.len(), 1);
let entity = entity_from_buf(&mut &*buffer).unwrap();
assert_eq!(entity, expected_entity);
}
#[test]
fn entity_with_generation() {
let expected_entity = Entity::from_index_and_generation(
EntityIndex::from_raw_u32(1).unwrap(),
EntityGeneration::from_bits(1),
);
let mut buffer = Vec::new();
entity_to_extend_mut(&expected_entity, &mut buffer).unwrap();
assert_eq!(buffer.len(), 2);
let entity = entity_from_buf(&mut &*buffer).unwrap();
assert_eq!(entity, expected_entity);
}
}