use hecs::serialize::column::{
deserialize_column, try_serialize, try_serialize_id, DeserializeContext, SerializeContext,
};
use hecs::{Archetype, ColumnBatchBuilder, ColumnBatchType, World};
use serde::{Deserialize, Serialize};
use std::any::TypeId;
use std::fs::File;
use std::io::{BufReader, Write};
use std::path::Path;
#[derive(Serialize, Deserialize)]
enum ComponentId {
ComponentA,
ComponentB,
}
#[derive(Default)]
struct SaveContextSerialize {}
#[derive(Default)]
struct SaveContextDeserialize {
components: Vec<ComponentId>,
}
#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
struct ComponentA {
data: usize,
}
#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
struct ComponentB {
some_other_data: String,
}
impl DeserializeContext for SaveContextDeserialize {
fn deserialize_component_ids<'de, A>(&mut self, mut seq: A) -> Result<ColumnBatchType, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
self.components.clear(); let mut batch = ColumnBatchType::new();
while let Some(id) = seq.next_element()? {
match id {
ComponentId::ComponentA => {
batch.add::<ComponentA>();
}
ComponentId::ComponentB => {
batch.add::<ComponentB>();
}
}
self.components.push(id);
}
Ok(batch)
}
fn deserialize_components<'de, A>(
&mut self,
entity_count: u32,
mut seq: A,
batch: &mut ColumnBatchBuilder,
) -> Result<(), A::Error>
where
A: serde::de::SeqAccess<'de>,
{
for component in &self.components {
match *component {
ComponentId::ComponentA => {
deserialize_column::<ComponentA, _>(entity_count, &mut seq, batch)?;
}
ComponentId::ComponentB => {
deserialize_column::<ComponentB, _>(entity_count, &mut seq, batch)?;
}
}
}
Ok(())
}
}
impl SerializeContext for SaveContextSerialize {
fn component_count(&self, archetype: &Archetype) -> usize {
archetype
.component_types()
.filter(|&t| t == TypeId::of::<ComponentA>() || t == TypeId::of::<ComponentB>())
.count()
}
fn serialize_component_ids<S: serde::ser::SerializeTuple>(
&mut self,
archetype: &Archetype,
mut out: S,
) -> Result<S::Ok, S::Error> {
try_serialize_id::<ComponentA, _, _>(archetype, &ComponentId::ComponentA, &mut out)?;
try_serialize_id::<ComponentB, _, _>(archetype, &ComponentId::ComponentB, &mut out)?;
out.end()
}
fn serialize_components<S: serde::ser::SerializeTuple>(
&mut self,
archetype: &Archetype,
mut out: S,
) -> Result<S::Ok, S::Error> {
try_serialize::<ComponentA, _>(archetype, &mut out)?;
try_serialize::<ComponentB, _>(archetype, &mut out)?;
out.end()
}
}
fn main() {
let mut world = World::new();
let input_data1 = ComponentA { data: 42 };
let input_data2 = ComponentB {
some_other_data: "Hello".to_string(),
};
world.spawn((input_data1.clone(),));
world.spawn((input_data2.clone(),));
let save_file_name = "saved_world.world";
let mut buffer: Vec<u8> = Vec::new();
let options = bincode::options();
let mut serializer = bincode::Serializer::new(&mut buffer, options);
hecs::serialize::column::serialize(
&world,
&mut SaveContextSerialize::default(),
&mut serializer,
)
.expect("Failed to serialize");
let path = Path::new(save_file_name);
let mut file = match File::create(path) {
Err(why) => panic!("couldn't create {}: {}", path.display(), why),
Ok(file) => file,
};
file.write_all(&buffer)
.unwrap_or_else(|_| panic!("Failed to write file: {save_file_name}"));
println!("Saved world \'{}\' to disk.", path.display());
let open = File::open(path).expect("not found!");
let reader = BufReader::new(open);
let mut deserializer = bincode::Deserializer::with_reader(reader, options);
match hecs::serialize::column::deserialize(
&mut SaveContextDeserialize::default(),
&mut deserializer,
) {
Ok(world) => {
println!("Loaded world \'{}\' from disk.", path.display());
print!("Validating world data... ");
assert_eq!(world.len(), 2);
for t in &mut world.query::<&ComponentA>() {
assert_eq!(t, &input_data1);
}
for t in &mut world.query::<&ComponentB>() {
assert_eq!(t, &input_data2);
}
println!("Ok!");
}
Err(err) => {
println!("Failed to deserialize world: {err}");
}
}
}