use bincode::{
config::{AllowTrailing, FixintEncoding, WithOtherIntEncoding, WithOtherTrailing},
de::read::SliceReader,
DefaultOptions, Options,
};
use rustc_hash::FxHashMap;
use serde::{de::Visitor, Deserializer, Serialize};
use std::marker::PhantomData;
use crate::{
Arena, ArenaEntry, BoxedComponent, ComponentController, ComponentManager, ComponentTypeId,
ComponentTypeStorage, Context, FieldNames, GroupHandle, Scene, SceneCreator, Shura,
StateDerive, StateIdentifier, StateManager, StateTypeId,
};
#[cfg(feature = "serde")]
#[derive(serde::Deserialize, serde::Serialize)]
pub(crate) enum SerializedComponentStorage {
Single(Option<Vec<u8>>),
Multiple(Vec<Option<(u32, Vec<u8>)>>),
MultipleGroups(Vec<(GroupHandle, Vec<Option<(u32, Vec<u8>)>>)>),
}
pub struct SceneSerializer<'a> {
components: &'a ComponentManager,
global_states: &'a StateManager,
scene_states: &'a StateManager,
ser_components: FxHashMap<ComponentTypeId, SerializedComponentStorage>,
ser_scene_states: FxHashMap<StateTypeId, Vec<u8>>,
ser_global_states: FxHashMap<StateTypeId, Vec<u8>>,
}
impl<'a> SceneSerializer<'a> {
pub(crate) fn new(
components: &'a ComponentManager,
global_states: &'a StateManager,
scene_states: &'a StateManager,
) -> Self {
Self {
components,
global_states,
scene_states,
ser_components: Default::default(),
ser_scene_states: Default::default(),
ser_global_states: Default::default(),
}
}
pub(crate) fn finish(
self,
) -> (
FxHashMap<ComponentTypeId, SerializedComponentStorage>,
FxHashMap<StateTypeId, Vec<u8>>,
FxHashMap<StateTypeId, Vec<u8>>,
) {
(
self.ser_components,
self.ser_scene_states,
self.ser_global_states,
)
}
pub fn serialize_components<C: ComponentController + serde::Serialize>(&mut self) {
let ty = self.components.type_ref::<C>();
let ser = match &ty.storage {
ComponentTypeStorage::Single { component, .. } => {
let data = if let Some(component) = &component {
bincode::serialize(component.downcast_ref::<C>().unwrap()).ok()
} else {
None
};
SerializedComponentStorage::Single(data)
}
ComponentTypeStorage::Multiple(multiple) => {
let ser_components = multiple.components.serialize_components::<C>();
SerializedComponentStorage::Multiple(ser_components)
}
ComponentTypeStorage::MultipleGroups(groups) => {
let mut group_data = vec![];
for (group_handle, group) in groups {
let ser_components = group.components.serialize_components::<C>();
group_data.push((GroupHandle(group_handle), ser_components));
}
SerializedComponentStorage::MultipleGroups(group_data)
}
};
self.ser_components.insert(C::IDENTIFIER, ser);
}
pub fn serialize_global_state<G: StateDerive + StateIdentifier + Serialize>(&mut self) {
if let Some(state) = self.global_states.try_get::<G>() {
self.ser_global_states
.insert(G::IDENTIFIER, bincode::serialize(state).unwrap());
}
}
pub fn serialize_scene_state<S: StateDerive + StateIdentifier + Serialize>(&mut self) {
if let Some(state) = self.scene_states.try_get::<S>() {
self.ser_scene_states
.insert(S::IDENTIFIER, bincode::serialize(state).unwrap());
}
}
}
pub struct SerializedScene<N: 'static + FnMut(&mut Context, &mut SceneDeserializer)> {
pub id: u32,
pub scene: Vec<u8>,
pub init: N,
}
impl<N: 'static + FnMut(&mut Context, &mut SceneDeserializer)> SerializedScene<N> {
pub fn new(id: u32, scene: Vec<u8>, init: N) -> SerializedScene<N> {
Self { id, scene, init }
}
}
impl<N: 'static + FnMut(&mut Context, &mut SceneDeserializer)> SceneCreator for SerializedScene<N> {
fn new_id(&self) -> u32 {
self.id
}
fn create(mut self: Box<Self>, shura: &mut Shura) -> Scene {
let (mut scene, ser_components, ser_scene_state, ser_global_state): (
Scene,
FxHashMap<ComponentTypeId, SerializedComponentStorage>,
FxHashMap<StateTypeId, Vec<u8>>,
FxHashMap<StateTypeId, Vec<u8>>,
) = bincode::deserialize(&self.scene).unwrap();
scene.id = self.id;
let mut de = SceneDeserializer::new(ser_components, ser_scene_state, ser_global_state);
let mut ctx = Context::new(shura, &mut scene);
(self.init)(&mut ctx, &mut de);
return scene;
}
}
#[derive(serde::Deserialize)]
pub struct SceneDeserializer {
ser_components: FxHashMap<ComponentTypeId, SerializedComponentStorage>,
ser_scene_states: FxHashMap<StateTypeId, Vec<u8>>,
ser_global_states: FxHashMap<StateTypeId, Vec<u8>>,
}
impl SceneDeserializer {
pub(crate) fn new(
ser_components: FxHashMap<ComponentTypeId, SerializedComponentStorage>,
ser_scene_states: FxHashMap<StateTypeId, Vec<u8>>,
ser_global_states: FxHashMap<StateTypeId, Vec<u8>>,
) -> Self {
Self {
ser_components,
ser_scene_states,
ser_global_states,
}
}
pub fn deserialize_components<C: serde::de::DeserializeOwned + ComponentController>(
&mut self,
ctx: &mut Context,
) {
ctx.components.reregister::<C>();
let type_id = C::IDENTIFIER;
let ty = ctx.components.type_mut::<C>();
if let Some(storage) = self.ser_components.remove(&type_id) {
match storage {
SerializedComponentStorage::Single(single) => match &mut ty.storage {
ComponentTypeStorage::Single { component, .. } => {
if let Some(single) = single {
*component =
Some(Box::new(bincode::deserialize::<C>(&single).unwrap()));
}
}
_ => unreachable!(),
},
SerializedComponentStorage::Multiple(ser_multiple) => match &mut ty.storage {
ComponentTypeStorage::Multiple(multiple) => {
let mut items: Vec<ArenaEntry<BoxedComponent>> =
Vec::with_capacity(ser_multiple.capacity());
let mut generation = 0;
for component in ser_multiple {
let item = match component {
Some((gen, data)) => {
generation = std::cmp::max(generation, gen);
let component: BoxedComponent =
Box::new(bincode::deserialize::<C>(&data).unwrap());
ArenaEntry::Occupied {
generation: gen,
data: component,
}
}
None => ArenaEntry::Free { next_free: None },
};
items.push(item);
}
let components = Arena::from_items(items, generation);
multiple.components = components;
}
_ => unreachable!(),
},
SerializedComponentStorage::MultipleGroups(ser_groups) => match &mut ty.storage {
ComponentTypeStorage::MultipleGroups(groups) => {
for (group_id, components) in ser_groups {
let mut items: Vec<ArenaEntry<BoxedComponent>> =
Vec::with_capacity(components.capacity());
let mut generation = 0;
for component in components {
let item = match component {
Some((gen, data)) => {
generation = std::cmp::max(generation, gen);
let component: BoxedComponent =
Box::new(bincode::deserialize::<C>(&data).unwrap());
ArenaEntry::Occupied {
generation: gen,
data: component,
}
}
None => ArenaEntry::Free { next_free: None },
};
items.push(item);
}
let components = Arena::from_items(items, generation);
groups[group_id.0].components = components;
}
}
_ => unreachable!(),
},
}
}
}
pub fn deserialize_components_with<C: ComponentController + FieldNames>(
&mut self,
ctx: &mut Context,
mut de: impl for<'de> FnMut(DeserializeWrapper<'de, C>, &'de Context<'de>) -> C,
) {
ctx.components.reregister::<C>();
let type_id = C::IDENTIFIER;
if let Some(storage) = self.ser_components.remove(&type_id) {
match storage {
SerializedComponentStorage::Single(single) => {
if let Some(single) = single {
let wrapper = DeserializeWrapper::new(&single);
let c: BoxedComponent = Box::new((de)(wrapper, ctx));
let ty = ctx.components.type_mut::<C>();
match &mut ty.storage {
ComponentTypeStorage::Single { component, .. } => {
*component = Some(c);
}
_ => unreachable!(),
}
}
}
SerializedComponentStorage::Multiple(ser_multiple) => {
let mut items: Vec<ArenaEntry<BoxedComponent>> =
Vec::with_capacity(ser_multiple.capacity());
let mut generation = 0;
for component in ser_multiple {
let item = match component {
Some((gen, data)) => {
generation = std::cmp::max(generation, gen);
let wrapper = DeserializeWrapper::new(&data);
let component: BoxedComponent = Box::new((de)(wrapper, ctx));
ArenaEntry::Occupied {
generation: gen,
data: component,
}
}
None => ArenaEntry::Free { next_free: None },
};
items.push(item);
}
let components = Arena::from_items(items, generation);
let ty = ctx.components.type_mut::<C>();
match &mut ty.storage {
ComponentTypeStorage::Multiple(multiple) => {
multiple.components = components;
}
_ => unreachable!(),
}
}
SerializedComponentStorage::MultipleGroups(ser_groups) => {
for (group_id, components) in ser_groups {
let mut items: Vec<ArenaEntry<BoxedComponent>> =
Vec::with_capacity(components.capacity());
let mut generation = 0;
for component in components {
let item = match component {
Some((gen, data)) => {
generation = std::cmp::max(generation, gen);
let wrapper = DeserializeWrapper::new(&data);
let component: BoxedComponent = Box::new((de)(wrapper, ctx));
ArenaEntry::Occupied {
generation: gen,
data: component,
}
}
None => ArenaEntry::Free { next_free: None },
};
items.push(item);
}
let ty = ctx.components.type_mut::<C>();
match &mut ty.storage {
ComponentTypeStorage::MultipleGroups(groups) => {
let components = Arena::from_items(items, generation);
groups[group_id.0].components = components;
}
_ => unreachable!(),
}
}
}
}
}
}
pub fn deserialize_global_state<
G: StateDerive + StateIdentifier + serde::de::DeserializeOwned,
>(
&mut self,
ctx: &mut Context,
) {
if let Some(ser_global_state) = self.ser_global_states.get(&G::IDENTIFIER) {
let de: G = bincode::deserialize(&ser_global_state).unwrap();
ctx.global_states.insert(de);
}
}
pub fn deserialize_scene_state<
S: StateDerive + StateIdentifier + serde::de::DeserializeOwned,
>(
&mut self,
ctx: &mut Context,
) {
if let Some(ser_scene_state) = self.ser_scene_states.get(&S::IDENTIFIER) {
let de: S = bincode::deserialize(&ser_scene_state).unwrap();
ctx.scene_states.insert(de);
}
}
pub fn deserialize_global_state_with<G: StateDerive + StateIdentifier + FieldNames>(
&mut self,
ctx: &mut Context,
mut de: impl for<'de> FnMut(DeserializeWrapper<'de, G>, &'de Context<'de>) -> G,
) {
if let Some(ser_global_state) = self.ser_global_states.get(&G::IDENTIFIER) {
let wrapper = DeserializeWrapper::new(&ser_global_state);
let state: G = (de)(wrapper, ctx);
ctx.global_states.insert(state);
}
}
pub fn deserialize_scene_state_with<S: StateDerive + StateIdentifier + FieldNames>(
&mut self,
ctx: &mut Context,
mut de: impl for<'de> FnMut(DeserializeWrapper<'de, S>, &'de Context<'de>) -> S,
) {
if let Some(ser_scene_state) = self.ser_scene_states.get(&S::IDENTIFIER) {
let wrapper = DeserializeWrapper::new(&ser_scene_state);
let state: S = (de)(wrapper, ctx);
ctx.scene_states.insert(state);
}
}
}
pub struct DeserializeWrapper<'de, F: FieldNames> {
de: bincode::Deserializer<
SliceReader<'de>,
WithOtherTrailing<WithOtherIntEncoding<DefaultOptions, FixintEncoding>, AllowTrailing>,
>,
_marker: PhantomData<F>,
}
impl<'de, F: FieldNames> DeserializeWrapper<'de, F> {
pub(crate) fn new(data: &'de [u8]) -> Self {
let options = bincode::DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes();
let de = bincode::Deserializer::from_slice(&data, options);
Self {
de,
_marker: PhantomData::<F>,
}
}
pub fn deserialize(mut self, visitor: impl Visitor<'de, Value = F>) -> F {
self.de.deserialize_struct("", F::FIELDS, visitor).unwrap()
}
}