hn.today

Rusty thoughts on "Parse, don't validate"

eli.thegreenplace.net94 points46 comments
Screenshot of Rusty thoughts on "Parse, don't validate"

This explains how encoding invariants in Rust types - “parsing” input into refined types - avoids repeated runtime validation and clarifies client code. It starts with the annoyance that Vec::first returns Option even when higher-level logic already ensured a vector is non-empty. The remedy is to change the function’s return type from Vec to a dedicated NonEmpty<T> (head plus tail) so construction establishes the invariant once (NonEmpty::from_vec returns Option<NonEmpty<T>>), and callers can use first() without handling None. Concrete snippets show how get_configuration_directories becomes simpler and safer when it returns NonEmpty<PathBuf> instead of Vec<PathBuf>.

Multiple real-world Rust examples illustrate the pattern: a coreutils rewrite uses NonEmpty for pipeline commands, rust-analyzer implements a layered refinement PathBuf -> camino::Utf8PathBuf -> AbsPathBuf so UTF‑8 and absoluteness are proven at construction, and std::num::NonZeroUsize models nonzero counts (available_parallelism returns NonZeroUsize, enabling no-zero checks and Option size optimizations). Serde deserialization similarly “parses” JSON directly into typed structures (enums, NonZeroUsize), moving validation into parsing. The practical payoff is stronger, compiler-checked guarantees, clearer call sites, fewer runtime checks, and occasional storage or panic-safety benefits, compared with ad hoc validation common in dynamic languages.

Read on eli.thegreenplace.net46 comments on Hacker News

Summary generated by AI from the linked article. hn.today is not affiliated with Hacker News or Y Combinator.

More in Programming

The daily digest

Today's best Hacker News stories, summarized and screenshotted, one email a day.