Contributing
Just recipes
Various just recipes are available, but these are the most useful:
just docs: run the docs site locallyjust validate: Test everything (lint, unit tests, etc.)
Design
confval is built around five design decisions. These design decisions underpin the core functionality of the crate and should be adhered to.
Spans travel with values.
- Every parsed value carries the byte range it came from.
- Any later check resolves that range to a line and column in the source file.
All errors are collected and displayed to an operator.
- Parsing and validation append to a shared report instead of returning on the first error.
- The caller fixes one batch of problems rather than rerunning to find the next one.
Validation happens in stages.
- Parsing checks shape only, meaning the field exists and has the right type.
- Range checks, closed sets, and cross-field rules run after parsing, in plain validation functions.
The core does not know any file format.
- Parsing produces a format-neutral field model.
- A frontend converts one syntax into that model.
- HCL and TOML ship today, each behind its own feature, and a new format is another frontend over the same model.
The core has no required dependencies.
serde, owo-colors, hcl-edit, toml_edit, and the derive macros are each behind a feature flag.
A goal of confval is to not require dependencies in the future. Any new dependencies should ideally be behind a feature flag.
Crate layout
confval is organized into four layers, each a module, plus a prelude.
The dependency direction is strictly downward: format builds on pipeline, which builds on diagnostic, which builds
on source.
| Module | Holds |
|---|---|
confval::source | Located, Span, SourceId, Source, SourceMap (the "where") |
confval::diagnostic | Report, Issue, IssueBuilder, Severity, the renderers (the "what") |
confval::pipeline | Lower, LowerAuto, Validate, narrow, RangeConstraint, KeywordSet (the transform) |
confval::format | the neutral field model (field) and the frontends (hcl, toml) |
confval::prelude | a glob re-export of the common imports across those layers |
use confval::prelude::*; pulls the everyday names (Located, Span, Report, Lower, Validate, narrow,
RangeConstraint, KeywordSet, and the derives) in one line.