use std::fmt::Display;
use serde::ser::{self, Serialize, SerializeSeq, Serializer};
use error::NoError;
use join::Join;
use saveload::EntityData;
use saveload::marker::{Marker, MarkerAllocator};
use storage::{GenericReadStorage, ReadStorage, WriteStorage};
use world::{Component, EntitiesRes, Entity};
pub trait IntoSerialize<M>: Component {
type Data: Serialize;
type Error;
fn into<F>(&self, ids: F) -> Result<Self::Data, Self::Error>
where
F: FnMut(Entity) -> Option<M>;
}
impl<C, M> IntoSerialize<M> for C
where
C: Clone + Component + Serialize,
{
type Data = Self;
type Error = NoError;
fn into<F>(&self, _: F) -> Result<Self::Data, Self::Error>
where
F: FnMut(Entity) -> Option<M>,
{
Ok(self.clone())
}
}
pub trait SerializeComponents<E, M>
where
M: Marker,
{
type Data: Serialize;
fn serialize_entity<F>(&self, entity: Entity, ids: F) -> Result<Self::Data, E>
where
F: FnMut(Entity) -> Option<M>;
fn serialize<'ms, S>(
&self,
entities: &EntitiesRes,
markers: &ReadStorage<M>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
E: Display,
S: Serializer,
{
let mut serseq = serializer.serialize_seq(None)?;
let ids = |entity| -> Option<M> { markers.get(entity).cloned() };
for (entity, marker) in (&*entities, &*markers).join() {
serseq.serialize_element(&EntityData::<M, Self::Data> {
marker: marker.clone(),
components: self.serialize_entity(entity, &ids)
.map_err(ser::Error::custom)?,
})?;
}
serseq.end()
}
fn serialize_recursive<MS, S>(
&self,
entities: &EntitiesRes,
markers: &mut WriteStorage<M>,
allocator: &mut M::Allocator,
serializer: S,
) -> Result<S::Ok, S::Error>
where
E: Display,
M: Marker,
S: Serializer,
{
let mut serseq = serializer.serialize_seq(None)?;
let mut to_serialize: Vec<(Entity, M)> = (entities, &*markers)
.join()
.map(|(e, m)| (e, m.clone()))
.collect();
while !to_serialize.is_empty() {
let mut add = vec![];
{
let mut ids = |entity| -> Option<M> {
if let Some((marker, added)) = allocator.mark(entity, markers) {
if added {
add.push((entity, marker.clone()));
}
Some(marker.clone())
} else {
None
}
};
for (entity, marker) in to_serialize {
serseq.serialize_element(&EntityData::<M, Self::Data> {
marker,
components: self.serialize_entity(entity, &mut ids)
.map_err(ser::Error::custom)?,
})?;
}
}
to_serialize = add;
}
serseq.end()
}
}
macro_rules! serialize_components {
($($comp:ident => $sto:ident,)*) => {
impl<'a, E, M, $($comp,)* $($sto,)*> SerializeComponents<E, M> for ($($sto,)*)
where
M: Marker,
$(
$sto: GenericReadStorage<Component = $comp>,
$comp : IntoSerialize<M>,
E: From<<$comp as IntoSerialize<M>>::Error>,
)*
{
type Data = ($(Option<$comp::Data>,)*);
#[allow(unused)]
fn serialize_entity<F>(&self, entity: Entity, mut ids: F) -> Result<Self::Data, E>
where
F: FnMut(Entity) -> Option<M>
{
#[allow(bad_style)]
let ($(ref $comp,)*) = *self;
Ok(($(
$comp.get(entity).map(|c| c.into(&mut ids).map(Some)).unwrap_or(Ok(None))?,
)*))
}
}
serialize_components!(@pop $($comp => $sto,)*);
};
(@pop) => {};
(@pop $head0:ident => $head1:ident, $($tail0:ident => $tail1:ident,)*) => {
serialize_components!($($tail0 => $tail1,)*);
};
}
serialize_components!(
CA => SA,
CB => SB,
CC => SC,
CD => SD,
CE => SE,
CF => SF,
CG => SG,
CH => SH,
);