Expand description
Save persistence with versioned migration chain.
Wire format on disk: a single JSON object with a "version": u32 field.
Pre-versioned saves (no field) are treated as V1 by migrate::peek_version.
Each version has a frozen struct in versions/vN.rs and a conversion into
the next version’s struct, walked end-to-end on load.
Once shipped, a versions/vN.rs is FROZEN. New schema changes go in
vN+1.rs together with a From<vN> for vN+1 impl and a unit test. See
the “Save versioning” section in CLAUDE.md for the full policy.
Callers (the Persistence impls under platform/) should never touch
serde_json on GameState directly — go through load_from_str /
save_to_string so the version dispatch stays in one place.
Modules§
- migrate
- Version-peeking helper for the save migration chain.
- versions
- Frozen save schemas — one module per shipped version.
Constants§
- CURRENT_
VERSION - The version number every fresh save is written as. Bump in lockstep
with adding a new
versions/vN.rsand routing it inload_from_str.
Functions§
- load_
from_ str - Best-effort load from a JSON string. Falls back to a default state if
the input is malformed at any layer of the chain. The result is always
passed through
GameState::migrate_runtimeso ephemeral#[serde(skip)]fields (flash vecs, count-up tweens, etc.) are seeded. - save_
to_ string - Serialize the live state to its on-disk JSON form. The
versionfield is whatever the caller has onstate—GameState::default()and the migration chain both stampCURRENT_VERSION, so the only way to write a wrong version is to mutatestate.versionby hand, which nothing does.