#![cfg(feature = "serde")]
#![cfg_attr(docsrs, feature(doc_cfg))]
use crate::{
cells::{Coord, State},
config::Config,
error::Error,
rules::Rule,
search::Reason,
traits::Search,
world::World,
};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ReasonSer {
Known,
Decide,
Rule(Coord),
Sym(Coord),
Deduce,
Clause(Vec<Coord>),
TryAnother(usize),
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub struct SetCellSer {
pub(crate) coord: Coord,
pub(crate) state: State,
pub(crate) reason: ReasonSer,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub struct WorldSer {
#[serde(default)]
config: Config,
#[serde(default)]
conflicts: u64,
#[serde(default)]
set_stack: Vec<SetCellSer>,
#[serde(default)]
check_index: u32,
}
impl WorldSer {
pub fn deser<'a, R: Rule, RE: Reason<'a, R>>(
&self,
world: &mut World<'a, R, RE>,
) -> Result<(), Error> {
for &SetCellSer {
coord,
state,
ref reason,
} in self.set_stack.iter()
{
let cell = world.find_cell(coord).ok_or(Error::SetCellError(coord))?;
if let Some(old_state) = cell.state.get() {
if old_state != state {
return Err(Error::SetCellError(coord));
}
} else if state.0 >= world.rule.gen() {
return Err(Error::SetCellError(coord));
} else {
let reason = RE::deser(reason, &world)?;
world.set_cell(cell, state, reason);
}
}
world.conflicts = self.conflicts;
if self.check_index < self.set_stack.len() as u32 {
world.check_index = self.check_index;
}
Ok(())
}
pub fn world(&self) -> Result<Box<dyn Search>, Error> {
let mut world = self.config.world()?;
world.deser(self)?;
Ok(world)
}
}
impl<'a, R: Rule, RE: Reason<'a, R>> World<'a, R, RE> {
pub fn ser(&self) -> WorldSer {
WorldSer {
config: self.config.clone(),
conflicts: self.conflicts,
set_stack: self.set_stack.iter().map(|s| s.ser()).collect(),
check_index: self.check_index,
}
}
}