rust-serdelisted
Install: claude install-skill po4yka/rust-skills
# Rust serde
## Purpose
Rules for types whose encoded form other code depends on. A `#[derive(Deserialize)]`
is a parser and a published schema at the same time, and the derive hides that. Most serde
incidents are not crashes; they are a field that silently stayed at its default, or a payload
an older build can no longer read.
Find what is at stake before you change a type:
```bash
# Every type whose encoding is a contract with something outside this process.
rg -n '#\[derive\([^)]*Deserialize' --type rust
# Attributes that change the wire format. Each one is a compatibility decision.
rg -n '#\[serde\((rename|rename_all|tag|untagged|flatten|skip)' --type rust
# Structs that accept anything they are given.
rg -L 'deny_unknown_fields' -l --type rust $(rg -l 'Deserialize' --type rust)
```
## Decide what the encoding is for
| The encoded form is | Rule |
| --- | --- |
| Internal to one process, one build, cache that may be discarded | Change it freely. Version the cache directory and drop it on mismatch |
| Written by a human: config, manifest, fixture | `deny_unknown_fields`. A typo must be an error, not a default |
| Read by an older build of your own code | Additive only. Every new field gets `default` |
| Read by another team or another language | Additive only, plus an explicit version field and a written schema |
The second and third rows conflict: `deny_unknown_fields` rejects a field a *newer* writer
added. Apply it to files a human authors, not to messages a new