diff --git a/card_game/src/lib.rs b/card_game/src/lib.rs index f011c16..7aea343 100644 --- a/card_game/src/lib.rs +++ b/card_game/src/lib.rs @@ -653,66 +653,46 @@ where } } +#[cfg_attr( + feature = "serde", + derive(serde_derive::Deserialize), + serde(bound = " + G: serde::Deserialize<'de>, + SessionConfig: serde::Deserialize<'de>, + Vec: serde::Deserialize<'de>, + ") +)] +struct SerializedSession { + config: SessionConfig, + state: G, + history: Vec, +} #[cfg(feature = "serde")] -impl<'de, G: Game> serde::de::DeserializeSeed<'de> for Session +impl<'de, G: Game> serde::de::Deserialize<'de> for Session where - G: serde::Deserialize<'de> + Clone, - G::Instruction: serde::Deserialize<'de>, + G: serde::Deserialize<'de> + Clone + Eq + core::hash::Hash, + G::Stats: Default, + G::Instruction: serde::Deserialize<'de> + Eq + core::hash::Hash, + SessionConfig: serde::Deserialize<'de>, + Vec: serde::Deserialize<'de>, { - type Value = SessionState; - fn deserialize(self, deserializer: D) -> Result + fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { - struct SessionStateVisitor { - state: G, - stats: SessionStats, - config: SessionConfig, + let serialized = SerializedSession::deserialize(deserializer)?; + let mut session = Session::new(serialized.state, serialized.config); + for instruction in serialized.history { + session.process_instruction(instruction); } - impl<'de, G: Game> serde::de::Visitor<'de> for SessionStateVisitor - where - G: serde::Deserialize<'de> + Clone, - G::Instruction: serde::Deserialize<'de>, - { - type Value = SessionState; - fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "State History") - } - fn visit_seq(mut self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - let mut state = self.state.clone(); - let mut history = match seq.size_hint() { - Some(capacity) => Vec::with_capacity(capacity), - None => Vec::new(), - }; - while let Some(instruction) = seq.next_element::()? { - history.push(StateSnapshot { - state: state.clone(), - instruction: instruction.clone(), - }); - state.process_instruction( - &mut self.stats.inner, - &self.config.inner, - instruction, - ); - } - Ok(SessionState { state, history }) - } - } - let state = G::deserialize(deserializer)?; - deserializer.deserialize_seq(SessionStateVisitor { - state, - stats: self.stats, - config: self.config, - }) + Ok(session) } } #[cfg(feature = "serde")] -impl serde::Serialize for SessionState +impl serde::Serialize for Session where G: serde::Serialize, + G::Config: serde::Serialize, G::Instruction: serde::Serialize, { fn serialize(&self, serializer: S) -> Result @@ -744,13 +724,14 @@ where // serialize the initial state of the game. // if there is history, it is the first snapshot's state, // otherwise it is the current game state since there are no moves. - let state = if let Some(snapshot) = self.history.first() { + let state = if let Some(snapshot) = self.state.history.first() { snapshot.state() } else { - &self.state + &self.state.state }; + map.serialize_entry("config", &self.config)?; map.serialize_entry("state", state)?; - map.serialize_entry("history", &History(&self.history))?; + map.serialize_entry("history", &History(&self.state.history))?; map.end() } }