specs 0.18.0

Specs is an Entity-Component-System library written in Rust.
Documentation
# Saveload

`saveload` is a module that provides mechanisms to serialize and deserialize a
`World`, it makes use of the popular [`serde`] library and requires the feature
flag `serde` to be enabled for `specs` in your `Cargo.toml` file.

At a high level, it works by defining a `Marker` component as well as a
`MarkerAllocator` resource. Marked entities will be the only ones subject to
serialization and deserialization.

`saveload` also defines `SerializeComponents` and `DeserializeComponents`,
these do the heavy lifting of exporting and importing.

Let's go over everything, point by point:

## `Marker` and `MarkerAllocator`

`Marker` and `MarkerAllocator<M: Marker>` are actually traits, simple
implementations are available with `SimpleMarker<T: ?Sized>` and
`SimpleMarkerAllocator<T: ?Sized>`, which you may use multiple times with
[Zero Sized Types].

```rust,ignore
struct NetworkSync;
struct FilePersistent;

fn main() {
    let mut world = World::new();

    world.register::<SimpleMarker<NetworkSync>>();
    world.insert(SimpleMarkerAllocator::<NetworkSync>::default());

    world.register::<SimpleMarker<FilePersistent>>();
    world.insert(SimpleMarkerAllocator::<FilePersistent>::default());

    world
        .create_entity()
        .marked::<SimpleMarker<NetworkSync>>()
        .marked::<SimpleMarker<FilePersistent>>()
        .build();
}

```

You may also roll your own implementations like so:

```rust,ignore
use specs::{prelude::*, saveload::{MarkedBuilder, Marker, MarkerAllocator}};

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[derive(serde::Serialize, serde::Deserialize)]
struct MyMarker(u64);

impl Component for MyMarker {
    type Storage = VecStorage<Self>;
}

impl Marker for MyMarker {
    type Identifier = u64;
    type Allocator = MyMarkerAllocator;

    fn id(&self) -> u64 {
        self.0
    }
}

#[derive(Clone, Debug, Default, Eq, PartialEq)]
struct MyMarkerAllocator(std::collections::HashMap<u64, Entity>);

impl MarkerAllocator<MyMarker> for MyMarkerAllocator {
    fn allocate(&mut self, entity: Entity, id: Option<u64>) -> MyMarker {
        let id = id.unwrap_or_else(|| self.unused_key()));
        self.0.insert(id, entity);
        MyMarker(id)
    }

    fn retrieve_entity_internal(&self, id: u64) -> Option<Entity> {
        self.0.get(&id).cloned()
    }

    fn maintain(
        &mut self,
        entities: &EntitiesRes,
        storage: &ReadStorage<MyMarker>,
    ) {
        // naive and possibly costly implementation, the techniques in
        // chapter 12 would be useful here!
        self.0 = (entities, storage)
            .join()
            .map(|(entity, marker)| (marker.0, entity))
            .collect();
    }
}

fn main() {
    let mut world = World::new();

    world.register::<MyMarker>();
    world.insert(MyMarkerAllocator::default());

    world
        .create_entity()
        .marked::<MyMarker>()
        .build();
}
```

Note that the trait `MarkedBuilder` must be imported to mark entities during
creation, it is implemented for `EntityBuilder` and `LazyBuilder`. Marking an
entity that is already present is straightforward:

```rust,ignore
fn mark_entity(
    entity: Entity,
    mut allocator: Write<SimpleMarkerAllocator<A>>,
    mut storage: WriteStorage<SimpleMarker<A>>,
) {
    use MarkerAllocator; // for MarkerAllocator::mark

    match allocator.mark(entity, &mut storage) {
        None => println!("entity was dead before it could be marked"),
        Some((_, false)) => println!("entity was already marked"),
        Some((_, true)) => println!("entity successfully marked"),
    }
}
```

## Serialization and Deserialization

As previously mentioned, `SerializeComponents` and `DeserializeComponents` are
the two heavy lifters. They're traits as well, however, that's just an
implementation detail, they are used like functions. They're implemented over
tuples of up to 16 `ReadStorage`/`WriteStorage`.

Here is an example showing how to serialize:

```rust,ignore
specs::saveload::SerializeComponents
    ::<Infallible, SimpleMarker<A>>
    ::serialize(
        &(position_storage, mass_storage),      // tuple of ReadStorage<'a, _>
        &entities,                              // Entities<'a>
        &marker_storage,                        // ReadStorage<'a, SimpleMarker<A>>
        &mut serializer,                        // serde::Serializer
    )   // returns Result<Serializer::Ok, Serializer::Error>
```

and now, how to deserialize:

```rust,ignore
specs::saveload::DeserializeComponents
    ::<Infallible, SimpleMarker<A>>
    ::deserialize(
        &mut (position_storage, mass_storage),  // tuple of WriteStorage<'a, _>
        &entities,                              // Entities<'a>
        &mut marker_storage,                    // WriteStorage<'a SimpleMarker<A>>
        &mut marker_allocator,                  // Write<'a, SimpleMarkerAllocator<A>>
        &mut deserializer,                      // serde::Deserializer
    )   // returns Result<(), Deserializer::Error>
```

As you can see, all parameters but one are `SystemData`, the easiest way to
access those would be through systems ([chapter on this subject][c6]) or by
calling `World::system_data`:

```rust,ignore
let (
    entities,
    mut marker_storage,
    mut marker_allocator,
    mut position_storage,
    mut mass_storage,
) = world.system_data::<(
    Entities,
    WriteStorage<SimpleMarker<A>>,
    Write<SimpleMarkerAllocator<A>>,
    WriteStorage<Position>,
    WriteStorage<Mass>,
)>();
```

Each `Component` that you will read from and write to must implement
`ConvertSaveload`, it's a benign trait and is implemented for all `Component`s
that are `Clone + serde::Serialize + serde::DeserializeOwned`, however you may
need to implement it (or derive it using [`specs-derive`]). In which case, you
may introduce more bounds to the first generic parameter and will need to
replace `Infallible` with a custom type, this custom type must implement
`From<<TheComponent as ConvertSaveload>::Error>` for all `Component`s,
basically.

[Zero Sized Types]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts
[`newtype`]: https://doc.rust-lang.org/1.0.0/style/features/types/newtype.html
[`serde`]: https://docs.rs/serde
[`specs-derive`]: https://docs.rs/specs-derive
[c6]: ./06_system_data.html