1mod de;
2mod ser;
3
4use alloc::string::String;
5pub use de::*;
6pub use ser::*;
7use serde::{Deserialize, Serialize};
8
9use crate::{
10 component::{ComponentKey, ComponentValue},
11 filter::And,
12 filter::{All, StaticFilter},
13 Component,
14};
15
16#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
17struct ComponentSerKey {
18 key: String,
19 id: ComponentKey,
20}
21
22#[derive(serde::Deserialize)]
23#[serde(field_identifier, rename_all = "lowercase")]
24enum WorldFields {
25 Archetypes,
26}
27
28#[derive(serde::Deserialize)]
29#[serde(field_identifier, rename_all = "lowercase")]
30enum RowFields {
31 Entities,
32}
33
34#[derive(Debug, Clone, serde::Deserialize)]
36pub enum SerializeFormat {
37 #[serde(rename = "row")]
42 RowMajor,
43 #[serde(rename = "col")]
46 ColumnMajor,
47}
48
49pub struct SerdeBuilder<F = All> {
52 ser: SerializeBuilder<F>,
53 de: DeserializeBuilder,
54}
55
56impl SerdeBuilder {
57 pub fn new() -> Self {
60 Self {
61 ser: Default::default(),
62 de: Default::default(),
63 }
64 }
65}
66
67impl Default for SerdeBuilder {
68 fn default() -> Self {
69 Self::new()
70 }
71}
72
73impl<F> SerdeBuilder<F>
74where
75 F: StaticFilter + 'static + Clone,
76{
77 pub fn with<T>(&mut self, component: Component<T>) -> &mut Self
81 where
82 T: ComponentValue + Serialize + for<'de> Deserialize<'de>,
83 {
84 self.with_name(component.name(), component)
85 }
86
87 pub fn with_name<T>(&mut self, key: impl Into<String>, component: Component<T>) -> &mut Self
89 where
90 T: ComponentValue + Serialize + for<'de> Deserialize<'de>,
91 {
92 let key = key.into();
93 self.ser.with_name(key.clone(), component);
94 self.de.with_name(key, component);
95 self
96 }
97
98 pub fn with_filter<G>(self, filter: G) -> SerdeBuilder<And<F, G>> {
100 SerdeBuilder {
101 ser: self.ser.with_filter(filter),
102 de: self.de,
103 }
104 }
105
106 pub fn build(&mut self) -> (SerializeContext, DeserializeContext) {
108 (self.ser.build(), self.de.build())
109 }
110}
111
112#[cfg(test)]
113mod test {
114 use alloc::format;
115 use alloc::vec;
116 use alloc::vec::Vec;
117 use rand::{
118 distributions::{Standard, Uniform},
119 rngs::StdRng,
120 Rng, SeedableRng,
121 };
122
123 use crate::{archetype::BatchSpawn, component, components::name, Entity, World};
124
125 use super::*;
126
127 #[test]
128 fn serialize() {
129 let mut world = World::new();
130
131 component! {
132 health: f32,
133 pos: (f32, f32),
134 items: Vec<String>,
135 status_effects: Vec<String>,
136 }
137
138 let player = Entity::builder()
139 .set(name(), "Player".into())
140 .set(pos(), (1.4, 5.3))
141 .set(items(), vec!["Dagger".into(), "Estradiol".into()])
142 .set(health(), 67.8)
143 .spawn(&mut world);
144
145 let mut rng = StdRng::seed_from_u64(42);
146
147 let mut batch = BatchSpawn::new(16);
148 batch
149 .set(name(), (0..).map(|i| format!("Enemy.{i}")))
150 .unwrap();
151 batch
152 .set(
153 health(),
154 (&mut rng)
155 .sample_iter(Uniform::new(0.0, 100.0))
156 .map(|v: f32| (v * 5.0).round() / 5.0),
157 )
158 .unwrap();
159
160 batch.set(pos(), (&mut rng).sample_iter(Standard)).unwrap();
161
162 let enemies = batch.spawn(&mut world);
163
164 world
165 .entry(enemies[2], status_effects())
166 .unwrap()
167 .or_default()
168 .push("Poison".into());
169
170 world
171 .entry(enemies[5], status_effects())
172 .unwrap()
173 .or_default()
174 .push("Fire".into());
175
176 let all_entities = [vec![player], enemies].concat();
177
178 let test_eq = |world: &World, new_world: &World| {
179 for &id in &all_entities {
181 assert_eq!(
182 world.get(id, health()).as_deref(),
183 new_world.get(id, health()).as_deref()
184 );
185
186 assert_eq!(
187 world.get(id, pos()).as_deref(),
188 new_world.get(id, pos()).as_deref()
189 );
190
191 assert_eq!(
192 world.get(id, items()).as_deref(),
193 new_world.get(id, items()).as_deref()
194 );
195
196 assert_eq!(
197 world.get(id, status_effects()).as_deref(),
198 new_world.get(id, status_effects()).as_deref()
199 );
200 }
201 };
202
203 let (serializer, deserializer) = SerdeBuilder::new()
204 .with(name())
205 .with(health())
206 .with(pos())
207 .with(items())
208 .with(status_effects())
209 .build();
210
211 let json =
212 serde_json::to_string(&serializer.serialize(&world, SerializeFormat::ColumnMajor))
213 .unwrap();
214
215 let new_world: World = deserializer
216 .deserialize(&mut serde_json::Deserializer::from_str(&json[..]))
217 .expect("Failed to deserialize world");
218
219 test_eq(&world, &new_world);
220
221 let json =
222 serde_json::to_string_pretty(&serializer.serialize(&world, SerializeFormat::RowMajor))
223 .unwrap();
224
225 let world = new_world;
226 let new_world = deserializer
227 .deserialize(&mut serde_json::Deserializer::from_str(&json[..]))
228 .expect("Failed to deserialize world");
229
230 test_eq(&world, &new_world);
231
232 let encoded =
233 ron::to_string(&serializer.serialize(&world, SerializeFormat::RowMajor)).unwrap();
234 let new_world = deserializer
235 .deserialize(&mut ron::Deserializer::from_str(&encoded).unwrap())
236 .unwrap();
237
238 test_eq(&world, &new_world);
239
240 let encoded =
241 ron::to_string(&serializer.serialize(&world, SerializeFormat::ColumnMajor)).unwrap();
242
243 let new_world = deserializer
244 .deserialize(&mut ron::Deserializer::from_str(&encoded).unwrap())
245 .unwrap();
246
247 test_eq(&world, &new_world);
248 }
249}