1use crate::{
4    cells::{Coord, State},
5    config::Config,
6    error::Error,
7    poly_world::PolyWorld,
8    rules::Rule,
9    search::{Algorithm, SetCell},
10    world::World,
11};
12use serde::{Deserialize, Serialize};
13use std::time::Duration;
14
15use std::collections::BTreeMap;
16
17#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
19pub enum ReasonSer {
20    Known,
22
23    Decide,
25
26    Rule(Coord),
28
29    Sym(Coord),
31
32    Deduce,
34
35    Clause(Vec<Coord>),
37
38    TryAnother(usize),
45}
46
47#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
49pub struct SetCellSer {
50    pub(crate) coord: Coord,
52
53    pub(crate) state: State,
55
56    pub(crate) reason: ReasonSer,
58}
59
60#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
62#[serde(default)]
63pub struct WorldSer {
64    pub config: Config,
66
67    pub conflicts: u64,
69
70    pub set_stack: Vec<SetCellSer>,
74
75    pub check_index: u32,
81
82    #[serde(skip_serializing_if = "Option::is_none")]
84    pub timing: Option<Duration>,
85
86    #[serde(skip_serializing_if = "BTreeMap::is_empty")]
88    pub extra: BTreeMap<String, String>,
89}
90
91impl WorldSer {
92    pub fn deser<R: Rule, A: Algorithm<R>>(&self, world: &mut World<R, A>) -> Result<(), Error> {
94        for &SetCellSer {
95            coord,
96            state,
97            ref reason,
98        } in &self.set_stack
99        {
100            let cell = world.find_cell(coord).ok_or(Error::SetCellError(coord))?;
101            if let Some(old_state) = cell.state.get() {
102                if old_state != state {
103                    return Err(Error::SetCellError(coord));
104                }
105            } else if state.0 >= world.rule.gen() {
106                return Err(Error::InvalidState(coord, state));
107            } else {
108                let reason = A::deser_reason(world, reason)?;
109                let cell = cell;
110                world.set_cell(cell, state, reason).ok();
111            }
112        }
113        world.conflicts = self.conflicts;
114        if self.check_index < self.set_stack.len() as u32 {
115            world.check_index = self.check_index;
116        }
117        Ok(())
118    }
119
120    pub fn world(&self) -> Result<PolyWorld, Error> {
122        let mut world = self.config.world()?;
123        world.deser(self)?;
124        Ok(world)
125    }
126}
127
128impl<R: Rule, A: Algorithm<R>> World<R, A> {
129    #[inline]
131    pub fn ser(&self) -> WorldSer {
132        WorldSer {
133            config: self.config.clone(),
134            conflicts: self.conflicts,
135            set_stack: self.set_stack.iter().map(SetCell::ser).collect(),
136            check_index: self.check_index,
137            timing: None,
138            extra: BTreeMap::new(),
139        }
140    }
141
142    #[inline]
144    pub fn deser(&mut self, ser: &WorldSer) -> Result<(), Error> {
145        ser.deser(self)
146    }
147}