Remove Saved* serde mirror types (migrate ReplayMove to upstream klondike serde) #89
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The
Saved*mirror types insolitaire_core/src/klondike_adapter.rs(SavedKlondikePile, SavedInstruction, SavedTableau, SavedFoundation, SavedSkipCards, SavedKlondikePileStack, SavedTableauStack, SavedDstFoundation, SavedDstTableau + their From/TryFrom impls — ~240 lines) exist solely because upstreamklondikelacked serde. It now has full serde:KlondikeInstructionhas a hand-written impl andKlondikePile/Tableau/Foundationderive Serialize/Deserialize.These mirrors are now pure wrapper duplication. They survive only because the persisted ReplayMove wire format still references
SavedKlondikePile(solitaire_data/src/replay.rs), mirrored insolitaire_wasm, plus the v3 save-migrationAnyInstruction::V3(SavedInstruction)path ingame_state.rs.Plan: bump the ReplayMove schema (v2 -> v3), switch its move fields from
SavedKlondikePileto upstreamklondike::KlondikePileserde, update the wasm mirror + in-repo JS (solitaire_server/web/game.js), keep a transparent v2->v3 deserialize shim for old replays, then delete the entireSaved*block.Coupled with #83 (card.rs / card_to_id): the same ReplayMove/wasm format also carries
card_to_idu32 ids; switching those tocard_game::Cardserde is the same wire-format change. Do #83 and this together as one 'ReplayMove v3' migration.Wire-format change — needs the v2 replay-load shim so existing replays still open.
Investigated — this issue's premise is wrong; the Saved pile mirrors are NOT removable.* A multi-agent attempt was reverted after the build proved it.
Root cause: upstream
klondike 0.4.0provides serde for the config types andKlondikeInstruction(hand-written, serializes as a u16 int), but its pile-position types —Tableau,Foundation,KlondikePile,KlondikePileStack— have NO serde derive (bare#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]at lib.rs 142/168/188/292). TheSaved*pile mirrors (SavedKlondikePile/SavedTableau/SavedFoundation) exist precisely to serialize pile positions forReplayMove, and that need is unchanged. MigratingReplayMove.from/totoKlondikePilefails to compile (KlondikePile: serde::Serializenot satisfied) in both solitaire_data and solitaire_wasm.The
Saved*instruction mirrors (SavedInstruction+SavedDst*/Saved*Stack) could be dropped in favour ofKlondikeInstructionserde — butinstruction_history()feeds the wasmmove_history/debug_move_historyJsValue API, so that too is a JS-facing wire-format change, not dead-code removal.Proper unlock (upstream): add
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]to the four klondike pile types upstream (one line each, matching the config types). Then the entire Saved* block becomes genuinely deletable. Until then these mirrors are necessary glue.Recommend: close as 'blocked on upstream klondike pile serde', or convert to an upstream klondike issue. The working tree is back at the green #82 commit; no changes landed.
Unblocked — revised approach (per upstream author). Asked Rhys to add serde to the klondike pile types; his answer: "It shouldn't need to serialize those for any reason, they are only relevant at runtime." He's right — pile positions are transient; you persist the moves, not the board coordinates.
So the fix is to stop serialising pile coordinates and persist
KlondikeInstructioninstead (it already has serde). Concretely:ReplayMovewas just the instruction history re-expressed in pile coords (instruction_history()->ReplayMove::Move{from,to,count}, then converted back on playback) — pure round-trip overhead.Plan now in progress:
solitaire_data::Replay.moves:Vec<ReplayMove>->Vec<KlondikeInstruction>; delete theReplayMoveenum.StockClickbecomesRotateStock(which already IS the stock-click input the engine resolves to draw/recycle).GameState::apply_instruction; UI pile coords recovered viaGameState::instruction_to_piles.Saved*mirror block + the v3 game_stateAnyInstructionmigration are deleted.Being implemented as a verified workspace change; no upstream klondike edits needed.