mod de;
mod ser;
use alloc::string::String;
pub use de::*;
pub use ser::*;
use serde::{Deserialize, Serialize};
use crate::{
component::{ComponentKey, ComponentValue},
filter::And,
filter::{All, StaticFilter},
Component,
};
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct ComponentSerKey {
key: String,
id: ComponentKey,
}
#[derive(serde::Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum WorldFields {
Archetypes,
}
#[derive(serde::Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum RowFields {
Entities,
}
#[derive(Debug, Clone, serde::Deserialize)]
pub enum SerializeFormat {
#[serde(rename = "row")]
RowMajor,
#[serde(rename = "col")]
ColumnMajor,
}
pub struct SerdeBuilder<F = All> {
ser: SerializeBuilder<F>,
de: DeserializeBuilder,
}
impl SerdeBuilder {
pub fn new() -> Self {
Self {
ser: Default::default(),
de: Default::default(),
}
}
}
impl Default for SerdeBuilder {
fn default() -> Self {
Self::new()
}
}
impl<F> SerdeBuilder<F>
where
F: StaticFilter + 'static + Clone,
{
pub fn with<T>(&mut self, component: Component<T>) -> &mut Self
where
T: ComponentValue + Serialize + for<'de> Deserialize<'de>,
{
self.with_name(component.name(), component)
}
pub fn with_name<T>(&mut self, key: impl Into<String>, component: Component<T>) -> &mut Self
where
T: ComponentValue + Serialize + for<'de> Deserialize<'de>,
{
let key = key.into();
self.ser.with_name(key.clone(), component);
self.de.with_name(key, component);
self
}
pub fn with_filter<G>(self, filter: G) -> SerdeBuilder<And<F, G>> {
SerdeBuilder {
ser: self.ser.with_filter(filter),
de: self.de,
}
}
pub fn build(&mut self) -> (SerializeContext, DeserializeContext) {
(self.ser.build(), self.de.build())
}
}
#[cfg(test)]
mod test {
use alloc::format;
use alloc::vec;
use alloc::vec::Vec;
use rand::{
distributions::{Standard, Uniform},
rngs::StdRng,
Rng, SeedableRng,
};
use crate::{archetype::BatchSpawn, component, components::name, Entity, World};
use super::*;
#[test]
fn serialize() {
let mut world = World::new();
component! {
health: f32,
pos: (f32, f32),
items: Vec<String>,
status_effects: Vec<String>,
}
let player = Entity::builder()
.set(name(), "Player".into())
.set(pos(), (1.4, 5.3))
.set(items(), vec!["Dagger".into(), "Estradiol".into()])
.set(health(), 67.8)
.spawn(&mut world);
let mut rng = StdRng::seed_from_u64(42);
let mut batch = BatchSpawn::new(16);
batch
.set(name(), (0..).map(|i| format!("Enemy.{i}")))
.unwrap();
batch
.set(
health(),
(&mut rng)
.sample_iter(Uniform::new(0.0, 100.0))
.map(|v: f32| (v * 5.0).round() / 5.0),
)
.unwrap();
batch.set(pos(), (&mut rng).sample_iter(Standard)).unwrap();
let enemies = batch.spawn(&mut world);
world
.entry(enemies[2], status_effects())
.unwrap()
.or_default()
.push("Poison".into());
world
.entry(enemies[5], status_effects())
.unwrap()
.or_default()
.push("Fire".into());
let all_entities = [vec![player], enemies].concat();
let test_eq = |world: &World, new_world: &World| {
for &id in &all_entities {
assert_eq!(
world.get(id, health()).as_deref(),
new_world.get(id, health()).as_deref()
);
assert_eq!(
world.get(id, pos()).as_deref(),
new_world.get(id, pos()).as_deref()
);
assert_eq!(
world.get(id, items()).as_deref(),
new_world.get(id, items()).as_deref()
);
assert_eq!(
world.get(id, status_effects()).as_deref(),
new_world.get(id, status_effects()).as_deref()
);
}
};
let (serializer, deserializer) = SerdeBuilder::new()
.with(name())
.with(health())
.with(pos())
.with(items())
.with(status_effects())
.build();
let json =
serde_json::to_string(&serializer.serialize(&world, SerializeFormat::ColumnMajor))
.unwrap();
let new_world: World = deserializer
.deserialize(&mut serde_json::Deserializer::from_str(&json[..]))
.expect("Failed to deserialize world");
test_eq(&world, &new_world);
let json =
serde_json::to_string_pretty(&serializer.serialize(&world, SerializeFormat::RowMajor))
.unwrap();
let world = new_world;
let new_world = deserializer
.deserialize(&mut serde_json::Deserializer::from_str(&json[..]))
.expect("Failed to deserialize world");
test_eq(&world, &new_world);
let encoded =
ron::to_string(&serializer.serialize(&world, SerializeFormat::RowMajor)).unwrap();
let new_world = deserializer
.deserialize(&mut ron::Deserializer::from_str(&encoded).unwrap())
.unwrap();
test_eq(&world, &new_world);
let encoded =
ron::to_string(&serializer.serialize(&world, SerializeFormat::ColumnMajor)).unwrap();
let new_world = deserializer
.deserialize(&mut ron::Deserializer::from_str(&encoded).unwrap())
.unwrap();
test_eq(&world, &new_world);
}
}