{
  "id": 10096696,
  "title": "Rusty thoughts on \"Parse, don't validate\"",
  "url": "https://urgent.news/2026/09/26/rusty-thoughts-on-parse-dont-validate",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-09-26T20:45:24.000Z",
  "source": {
    "name": "Lobsters",
    "slug": "lobsters",
    "url": "https://eli.thegreenplace.net/2026/rusty-thoughts-on-parse-dont-validate/"
  },
  "original_language": "en",
  "account": "The \"Parse, don't validate\" article by Alexis King intrigued many programmers, as it highlights a familiar, valuable coding approach that has been observed and utilized previously without a formal name. This review focuses on the pattern's application in Rust programming, drawing insights from the original post which employs Haskell.\n\nThe concept begins with the Vec type in Rust, whose 'first' method returns an Option<&T>. This is due to vectors potentially having no elements, making it unclear what to do if 'first' is called on an empty vector. To address this, Rust uses the Option type for idiomatic handling, with convenient syntax for dealing with results that may or may not exist. Consider a function that reads configuration paths from an environment variable, enforcing the rule that the list cannot be empty.\n\nThe challenge arises when using the 'first' method on the resulting vector. If the function returns a successful result, the vector is guaranteed not to be empty. However, accessing the first element still requires handling a potential empty case. The core issue lies in the lack of a formally enforced check that the vector cannot be empty. The solution involves leveraging Rust's type system to enforce a new invariant. A separate type, such as NonEmpty, can be used to ensure a vector cannot be empty. This type prevents the possibility of creating an empty vector during construction and provides a first method that returns &T without an Option.\n\nSeveral Rust crates, like nonempty, already implement NonEmpty, allowing it to behave similarly to Vec while enforcing the non-empty invariant. Using NonEmpty in functions like get_configuration_directories eliminates the need to repeatedly check for an empty list, as the type system enforces this constraint. This approach aligns with the \"parse vs. validate\" terminology from King's article. When get_configuration_directories returns a Vec, it validates the input but leaves the responsibility of ensuring the vector is non-empty to the caller. In contrast, returning a NonEmpty type enforces the non-emptiness at the type level, simplifying client code.\n\nThe \"parse, don't validate\" pattern extends beyond Vec. Rust's core POSIX utilities rewrite uses NonEmpty in various scenarios, such as constructing a shell pipeline where a valid Pipeline is returned only if there are commands in the parsed Abstract Syntax Tree (AST). If no commands are present, the Pipeline returns None. This approach eliminates the need to check for a None value in client code after parsing.\n\nAnother example comes from rust-analyzer, a project that represents absolute filesystem paths using AbsPathBuf, a type that enforces the path's absoluteness. The AbsPathBuf type wraps Utf8PathBuf, a custom type refinement ensuring valid UTF-8 paths. This gradual parsing and type refinement ensure path validity without the need for constant validation checks in subsequent code.\n\nRust's NonZero type further illustrates the \"parse, don't validate\" pattern. Numeric types like NonZeroUsize enforce that their values are never zero. When used as the denominator in division operations, they cannot panic, as zero is an invalid value for the type. This enshrines the non-zero constraint in the type system, eliminating the need for explicit validation checks.\n\nIn JSON deserialization, the serde crate exemplifies the \"parse, don't validate\" idiom. Deserializing data from a JSON string parses the data, and the resulting types inherently carry validated information. For instance, converting a JSON string to a Rust enum eliminates the need for additional validation after parsing. In dynamic languages like Python or JavaScript, similar processes often require manual validation of parsed data, making Rust's approach more streamlined.\n\nOverall, the \"parse, don't validate\" pattern is a powerful technique for enforcing invariants at the type level, reducing the need for manual validation checks and improving code clarity. This approach, seen across various Rust projects, demonstrates its versatility and effectiveness in managing data integrity and simplifying client code.",
  "summary": null,
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}