Failed World::clone_from(), because of missing Duplicate::register_clone(), asserts
singalen opened this issue · 0 comments
singalen commented
This code tries to implement the request from #269 – to deserialize into an existing World and to find out what exactly we have deserialized.
I didn't realize one needs Duplicate::register_clone()
or Duplicate::register_copy()
in order to copy/clone anything between World
s.
As a result, the following crashes:
use std::{fs, fmt, io};
use std::ops::Range;
use std::path::Path;
use std::error::Error;
use std::fmt::{Display, Formatter};
use serde::de::DeserializeSeed;
use legion::{Entity, World};
use legion::serialize::Canon;
use legion::world::{Merger, Duplicate, Allocate};
use crate::item::{Item, Headwear};
use crate::components::Render;
use crate::prelude::storage::{Archetype, Components, ArchetypeWriter};
impl Registry {
pub fn new() -> Self {
let mut result = Self { registry: legion::Registry::<String>::default() };
result.registry.register::<Render>("render".to_string());
result.registry.register::<Item>("item".to_string());
result.registry.register::<Headwear>("headwear".to_string());
result
}
fn deser(&self, item_name: &str) -> Result<World, PrefabError> {
let path = Path::new("data/items").join(item_name).with_extension("json");
let json = fs::read_to_string(path)?;
let json_val: serde_json::Value = serde_json::from_str(&json)?;
let entity_serializer = Canon::default();
let w = self.registry
.as_deserialize(&entity_serializer)
.deserialize(json_val)?;
Ok(w)
}
pub fn load(&self, item_name: &str, world: &mut World) -> Result<Vec<Entity>, PrefabError> {
struct PrefabMerger {
pub dup: Duplicate,
pub entities: Vec<Entity>,
}
impl Merger for PrefabMerger {
fn assign_id(&mut self, existing: Entity, allocator: &mut Allocate) -> Entity {
let id = self.dup.assign_id(existing, allocator);
self.entities.push(id);
id
}
fn merge_archetype(&mut self, src_entity_range: Range<usize>, src_arch: &Archetype, src_components: &Components, dst: &mut ArchetypeWriter) {
self.dup.merge_archetype(src_entity_range, src_arch, src_components, dst)
}
}
impl PrefabMerger {
pub fn new() -> Self {
Self { dup: Duplicate::default(), entities: vec![] }
}
}
let mut mirage_world = self.deser(item_name)?;
let mut merger = PrefabMerger::new();
world.clone_from(&mut mirage_world, &legion::any(), &mut merger);
Ok(merger.entities)
}
}
#[cfg(test)]
mod tests {
#[test]
fn cask() -> Result<(), PrefabError> {
let mut world = World::default();
let reg = Registry::new();
let entities = reg.load("one_cask", &mut world)?;
assert_eq!(1, entities.len());
Ok(())
}
}
It fails with the following stack:
3: core::panicking::assert_failed
at /Users/vic/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/panicking.rs:143:5
4: <legion::internals::insert::ArchetypeWriter as core::ops::drop::Drop>::drop
at /Users/vic/.cargo/registry/src/github.com-1ecc6299db9ec823/legion-0.4.0/src/internals/insert.rs:113:9
5: core::ptr::drop_in_place<legion::internals::insert::ArchetypeWriter>
at /Users/vic/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:192:1
6: legion::internals::world::World::clone_from
at /Users/vic/.cargo/registry/src/github.com-1ecc6299db9ec823/legion-0.4.0/src/internals/world.rs:691:9
7: rifrl::item::prefabs::Registry::load
at ./src/item/prefabs.rs:103:9
8: rifrl::item::prefabs::tests::cask
at ./src/item/prefabs.rs:183:24
in impl Drop for ArchetypeWriter::drop()
:
assert_eq!(
self.claimed.count_ones() as usize,
self.archetype.layout().component_types().len()
);
I guess this should not crash, but instead just clone nothing. Or, maybe, it should, but with a more clear error message.