Enums and Pattern Matching: The Exhaustiveness Invariant
Enums let you define a type by listing its possible variants. match forces you to handle every single one. The compiler guarantees you never forget a case — and Option
Enums let you define a type by listing its possible variants. match forces you to handle every single one. The compiler guarantees you never forget a case — and Option
Invariants aren't just for distributed systems. They're in every parser, every format, every function boundary. Here's where I found them while implementing TOON in Rust.
Instantiate, Execute, Query — three message types, three classes of invariants. How CosmWasm contracts enforce valid state transitions through typed messages and ownership checks.
Smart contracts don't have main(). They have entry points — and each one enforces a different invariant about how the outside world can interact with on-chain state.
Every .unwrap() is an invariant you haven't enforced. Proper error handling transforms silent crashes into explicit contracts about what can go wrong and how the program responds.
The decrypt command closes the loop. The round-trip invariant — decrypt(encrypt(plaintext, key), key) == plaintext — is the single property that proves the entire system works. If it fails, nothing else matters.
Encryption is an invariant transformation: given a key K and plaintext P, the ciphertext C must be deterministic, reversible with K, and indistinguishable from random data without K. The encrypt command must uphold all three properties.
A cryptographic key that is too short, predictable, or improperly encoded is worse than no key at all. The generate command must uphold a strict invariant: the output is always a correctly-sized, random, properly-encoded secret.
Every CLI application is a contract between the program and the user. Clap helps us encode that contract as invariants — required arguments, valid subcommands, and structured input — enforced before a single line of business logic runs.
Structs let you define your own types — and your own invariants. By controlling construction, field access, and method behavior, you decide what 'valid' means for your data.