use crate::entity::EntityId;
use crate::error::{EcsError, Result};
use crate::reflection::Reflect;
use crate::world::World;
use serde::{Deserialize, Serialize};
use std::any::TypeId;
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Scene {
pub entities: Vec<EntityData>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EntityData {
pub id: u64,
pub components: HashMap<String, serde_json::Value>,
}
impl Scene {
pub fn new() -> Self {
Self {
entities: Vec::new(),
}
}
pub fn entity_count(&self) -> usize {
self.entities.len()
}
}
impl Default for Scene {
fn default() -> Self {
Self::new()
}
}
pub trait ComponentSerializer: Send + Sync {
fn serialize_json(&self, component: &dyn Reflect) -> Result<serde_json::Value>;
fn deserialize_json(&self, value: &serde_json::Value) -> Result<Box<dyn Reflect>>;
fn type_name(&self) -> &'static str;
}
struct TypedComponentSerializer<T: Reflect + Serialize + for<'de> Deserialize<'de> + Clone> {
_phantom: std::marker::PhantomData<T>,
}
impl<T: Reflect + Serialize + for<'de> Deserialize<'de> + Clone> TypedComponentSerializer<T> {
fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
impl<T: Reflect + Serialize + for<'de> Deserialize<'de> + Clone + 'static> ComponentSerializer
for TypedComponentSerializer<T>
{
fn serialize_json(&self, component: &dyn Reflect) -> Result<serde_json::Value> {
let concrete = component
.as_any()
.downcast_ref::<T>()
.ok_or_else(|| EcsError::SerializationError("Type mismatch".to_string()))?;
serde_json::to_value(concrete).map_err(|e| EcsError::SerializationError(e.to_string()))
}
fn deserialize_json(&self, value: &serde_json::Value) -> Result<Box<dyn Reflect>> {
let component: T = serde_json::from_value(value.clone())
.map_err(|e| EcsError::SerializationError(e.to_string()))?;
Ok(Box::new(component))
}
fn type_name(&self) -> &'static str {
std::any::type_name::<T>()
}
}
pub struct SerializationRegistry {
serializers: HashMap<TypeId, Box<dyn ComponentSerializer>>,
type_names: HashMap<String, TypeId>,
}
impl SerializationRegistry {
pub fn new() -> Self {
Self {
serializers: HashMap::new(),
type_names: HashMap::new(),
}
}
pub fn register<T>(&mut self)
where
T: Reflect + Serialize + for<'de> Deserialize<'de> + Clone + 'static,
{
let type_id = TypeId::of::<T>();
let type_name = std::any::type_name::<T>().to_string();
self.serializers
.insert(type_id, Box::new(TypedComponentSerializer::<T>::new()));
self.type_names.insert(type_name, type_id);
}
pub fn get_serializer(&self, type_id: TypeId) -> Option<&dyn ComponentSerializer> {
self.serializers.get(&type_id).map(|s| s.as_ref())
}
pub fn get_type_id(&self, type_name: &str) -> Option<TypeId> {
self.type_names.get(type_name).copied()
}
}
impl Default for SerializationRegistry {
fn default() -> Self {
Self::new()
}
}
pub fn save_world(world: &World, registry: &SerializationRegistry) -> Result<Scene> {
let mut scene = Scene::new();
for archetype in world.archetypes() {
for &entity_id in archetype.entities().iter() {
let entity_data = EntityData {
id: unsafe { std::mem::transmute::<EntityId, u64>(entity_id) },
components: HashMap::new(),
};
for &component_type in archetype.signature() {
if let Some(serializer) = registry.get_serializer(component_type) {
if let Some(_column) = archetype.get_column(component_type) {
let _type_name = serializer.type_name();
continue;
}
}
}
if !entity_data.components.is_empty() {
scene.entities.push(entity_data);
}
}
}
Ok(scene)
}
pub fn load_world(
_world: &mut World,
_scene: &Scene,
_registry: &SerializationRegistry,
) -> Result<HashMap<u64, EntityId>> {
let id_map = HashMap::new();
Ok(id_map)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_scene_creation() {
let scene = Scene::new();
assert_eq!(scene.entity_count(), 0);
}
#[test]
fn test_serialization_registry() {
let mut registry = SerializationRegistry::new();
registry.register::<i32>();
registry.register::<f32>();
assert!(registry.get_serializer(TypeId::of::<i32>()).is_some());
assert!(registry.get_serializer(TypeId::of::<f32>()).is_some());
}
}