flax 0.7.1

An ergonomic archetypical ECS
Documentation
extern crate alloc;
use alloc::string::String;
use flax::{component, error::MissingComponent, CommandBuffer, Entity, Error, Exclusive, World};
use std::sync::Arc;

component! {
    a: i32,
    b: String,

    relation(id): Arc<()> => [ Exclusive ],
}

#[test]
fn entity_builder() {
    let mut world = World::new();

    let id1 = Entity::builder()
        .set(a(), 1)
        .set(b(), "hello".into())
        .spawn(&mut world);

    let mut id2 = Entity::builder();
    id2.set(a(), 2).set(b(), "hello".into());
    id2.remove(b());

    let id2 = id2.spawn(&mut world);

    assert_eq!(world.get(id2, a()).as_deref(), Ok(&2));
    assert_eq!(
        world.get(id2, b()).as_deref(),
        Err(&Error::MissingComponent(MissingComponent {
            id: id2,
            desc: b().desc()
        }))
    );

    let value = Arc::new(());

    let mut id3 = Entity::builder();
    id3.set(a(), 3);
    id3.set(b(), "world".into());
    id3.set(relation(id2), value.clone());

    assert_eq!(Arc::strong_count(&value), 2);

    id3.set(relation(id1), value.clone());

    assert_eq!(Arc::strong_count(&value), 2);

    let id3 = id3.spawn(&mut world);
    assert_eq!(Arc::strong_count(&value), 2);

    assert_eq!(world.get(id3, a()).as_deref(), Ok(&3));
    assert_eq!(world.get(id3, relation(id1)).as_deref(), Ok(&value));
    assert_eq!(
        world.get(id3, relation(id2)).as_deref(),
        Err(&Error::MissingComponent(MissingComponent {
            id: id3,
            desc: relation(id2).desc()
        }))
    );

    world.despawn(id3).unwrap();
    assert_eq!(Arc::strong_count(&value), 1);
}

#[test]
fn entity_builder_cmd() {
    let mut world = World::new();

    let id1 = Entity::builder()
        .set(a(), 1)
        .set(b(), "hello".into())
        .spawn(&mut world);

    let mut id2 = Entity::builder();
    id2.set(a(), 2).set(b(), "hello".into());
    id2.remove(b());

    let id2 = id2.spawn(&mut world);

    assert_eq!(world.get(id2, a()).as_deref(), Ok(&2));
    assert_eq!(
        world.get(id2, b()).as_deref(),
        Err(&Error::MissingComponent(MissingComponent {
            id: id2,
            desc: b().desc()
        }))
    );

    let value = Arc::new(());

    let id3 = world.spawn();
    let mut cmd = CommandBuffer::new();
    cmd.set(id3, a(), 4);
    cmd.set(id3, b(), "world".into());
    cmd.set(id3, relation(id2), value.clone());

    assert_eq!(Arc::strong_count(&value), 2);

    cmd.set(id3, relation(id1), value.clone());

    cmd.apply(&mut world).unwrap();

    assert_eq!(world.get(id3, a()).as_deref(), Ok(&4));
    assert_eq!(world.get(id3, relation(id1)).as_deref(), Ok(&value));
    assert_eq!(
        world.get(id3, relation(id2)).as_deref(),
        Err(&Error::MissingComponent(MissingComponent {
            id: id3,
            desc: relation(id2).desc()
        }))
    );

    assert_eq!(Arc::strong_count(&value), 2);

    world.despawn(id3).unwrap();
    assert_eq!(Arc::strong_count(&value), 1);
}
#[test]
fn test_append() {
    let mut world = World::new();

    let id1 = Entity::builder()
        .set(a(), 1)
        .set(b(), "hello".into())
        .spawn(&mut world);

    let id2 = Entity::builder()
        .set(a(), 1)
        .set(b(), "hello".into())
        .spawn(&mut world);

    let id3 = world.spawn();

    let mut builder = Entity::builder();

    let value = Arc::new(());
    builder.set(a(), 5).set(relation(id2), value.clone());

    builder.append_to(&mut world, id3).unwrap();

    assert_eq!(Arc::strong_count(&value), 2);
    assert!(world.has(id3, relation(id2)));
    assert!(!world.has(id3, relation(id1)));

    let mut builder = Entity::builder();

    builder.set(relation(id1), value.clone());

    assert_eq!(Arc::strong_count(&value), 3);

    builder.append_to(&mut world, id3).unwrap();
    // The old relation is dropped
    assert_eq!(Arc::strong_count(&value), 2);
    assert!(!world.has(id3, relation(id2)));
    assert!(world.has(id3, relation(id1)));
}