spru 0.1.0

Reusable components for the spru strategy and digital board game framework.
Documentation
use std::{marker::PhantomData, sync::Arc};

use derive_where::derive_where;

use crate::{common, item};

#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct SnapshotType<Index> {
    index: Index,
    items: Box<[item::Erased]>,
}

#[derive_where(Debug, Serialize, Deserialize; Repr, Root)]
pub(crate) struct Snapshot<Repr, State, Root> {
    root: Root,
    items: Arc<[SnapshotType<Repr>]>,
    #[serde(skip)]
    _p: PhantomData<fn(State) -> State>,
}

impl<State: tagset::TagSet<Repr: Clone>, Root> Snapshot<State::Repr, State, Root> {
    pub(crate) fn new(
        root: Root,
        storage: &item::storage::Canonical<State::Repr, State>,
    ) -> Result<Self, common::error::Save> {
        let mut snapshot_items_map = vec![];
        for (key, item_map) in storage.items_map().iter() {
            snapshot_items_map.push(SnapshotType {
                index: key.clone(),
                items: item_map.as_serialized()?,
            });
        }

        Ok(Self {
            root,
            items: snapshot_items_map.into(),
            _p: Default::default(),
        })
    }

    pub(crate) fn root(&self) -> &Root {
        &self.root
    }

    pub(crate) fn apply<Storage>(&self, storage: &mut Storage) -> Result<(), common::error::Load>
    where
        State: crate::State,
        Storage: item::Storage<State = State>,
    {
        for item_type in &*self.items {
            for item in &*item_type.items {
                State::apply_state(item_type.index.clone(), item, storage)?;
            }
        }
        Ok(())
    }
}