#![cfg(feature = "serialize")]
use crate::{
cells::{Coord, State},
config::Config,
error::Error,
rules::{Life, LifeGen, NtLife, NtLifeGen, Rule},
search::{Reason, SetCell},
traits::Search,
world::World,
};
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
struct SetCellSer {
coord: Coord,
state: State,
reason: Reason,
}
impl<'a, R: Rule> SetCell<'a, R> {
fn ser(&self) -> SetCellSer {
SetCellSer {
coord: self.cell.coord,
state: self.cell.state.get().unwrap(),
reason: self.reason,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorldSer {
config: Config,
conflicts: u64,
set_stack: Vec<SetCellSer>,
check_index: usize,
search_index: usize,
}
impl WorldSer {
fn world_with_rule<'a, R: Rule>(&self, rule: R) -> Result<World<'a, R>, Error> {
let mut world = World::new(&self.config, rule);
for &SetCellSer {
coord,
state,
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 {
world.set_cell(cell, state, reason);
}
}
world.conflicts = self.conflicts;
world.check_index = self.check_index;
world.search_index = self.search_index;
Ok(world)
}
pub fn world(&self) -> Result<Box<dyn Search>, Error> {
if let Ok(rule) = self.config.rule_string.parse::<Life>() {
let world = self.world_with_rule(rule)?;
Ok(Box::new(world))
} else if let Ok(rule) = self.config.rule_string.parse::<NtLife>() {
let world = self.world_with_rule(rule)?;
Ok(Box::new(world))
} else if let Ok(rule) = self.config.rule_string.parse::<LifeGen>() {
if rule.gen() > 2 {
let world = self.world_with_rule(rule)?;
Ok(Box::new(world))
} else {
let rule = rule.non_gen();
let world = self.world_with_rule(rule)?;
Ok(Box::new(world))
}
} else {
let rule = self
.config
.rule_string
.parse::<NtLifeGen>()
.map_err(Error::ParseRuleError)?;
if rule.gen() > 2 {
let world = self.world_with_rule(rule)?;
Ok(Box::new(world))
} else {
let rule = rule.non_gen();
let world = self.world_with_rule(rule)?;
Ok(Box::new(world))
}
}
}
}
impl<'a, R: Rule> World<'a, R> {
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,
search_index: self.search_index,
}
}
}