soothfast-docs API reference#
Generated by
cargo soothfast docs referenceMeasurements and verified claims come from the latest baseline; CI gates them.
soothfast_docs#
soothfast_docs::claims#
Claim struct#
pub struct Claim { pub item: String, pub backend: String, pub metric: String, pub op: Op, pub bound: f64 }
One parsed soothfast:claim expression: a measured metric of an item,
compared against a fixed bound.
Op enum#
pub enum Op { Lt, Le, Gt, Ge }
Comparison operator of a claim expression (<, <=, >, >=).
evaluate function#
pub fn evaluate(claim: &Claim, baseline: &Value) -> Result<(bool, f64), String>
Evaluate against a baseline document; returns (holds, actual value).
parse function#
pub fn parse(expr: &str) -> Result<Claim, String>
Parse demo::lcg_checksum.perfcnt.instructions < 25000 (units on the
bound: ns/us/ms/s multiply into ns; bare numbers stay raw).
soothfast_docs::diff#
SurfaceDiff struct#
pub struct SurfaceDiff { pub added: Vec<String>, pub removed: Vec<String>, pub changed: Vec<(String, bool)> }
Public-API delta between two [Surface] snapshots, by item path.
compare function#
pub fn compare(old: &Surface, new: &Surface) -> SurfaceDiff
Diff two surfaces: added/removed items by path, changed items by span fingerprint (modules are exempt — their span is the whole file).
render function#
pub fn render(diff: &SurfaceDiff) -> String
One ADDED/REMOVED/CHANGED line per item, ready for terminals and
changelog drafts; an empty diff renders as a single "no changes" line.
soothfast_docs::gentests#
CAPTURE_DIR constant#
pub const CAPTURE_DIR: &str = "examples/soothfast_capture"
The one example target every capture block of a package compiles into.
CAPTURE_DISABLED constant#
pub const CAPTURE_DISABLED: (i32, &str) = (3, "soothfast_capture: disabled block")
Exit status of the capture example for a block whose feature= tag is
not enabled in this build. The stderr line starts with the sentinel.
CAPTURE_EXAMPLE constant#
pub const CAPTURE_EXAMPLE: &str = "soothfast_capture"
Cargo's name for the [CAPTURE_DIR] example.
CAPTURE_UNKNOWN constant#
pub const CAPTURE_UNKNOWN: (i32, &str) = (2, "soothfast_capture: unknown block")
Exit status of the capture example for a block id it does not contain.
DOC_TESTS_DIR constant#
pub const DOC_TESTS_DIR: &str = "tests/soothfast_docs"
The one integration-test target the doc tests of a package compile into.
GENERATED_HEADER constant#
pub const GENERATED_HEADER: &str = "// @generated by `cargo soothfast docs gen-tests`"
First line of every generated file; docs check uses it to tell
generated artifacts from hand-written ones.
Generated struct#
pub struct Generated { pub path: String, pub content: String }
One generated file, its path relative to the package directory.
OWNED constant#
pub const OWNED: &[(&str, &str, Option<&str>)] = &[ ("tests", "soothfast_doc_", Some(DOC_TESTS_DIR)), (DOC_TESTS_DIR, "", None), ("examples", "soothfast_capture_", Some(CAPTURE_DIR)), (CAPTURE_DIR, "", None), ]
Where generated files live, as (directory, file-name prefix, replaced by),
relative to the package directory. A file there that starts with
[GENERATED_HEADER] belongs to gen-tests: it is rewritten when expected
and removed when not. An entry with an empty prefix is a target directory
gen-tests owns outright; a prefixed entry is the per-page or per-block
layout of earlier releases and names the target directory that replaced it.
capture_ids function#
pub fn capture_ids(rel_path: &str, doc: &Doc) -> Vec<String>
Block ids for one page's capture blocks, in capture order: the argument the capture example takes to run that block.
capture_set function#
pub fn capture_set<'a>( docs: impl IntoIterator<Item = (&'a str, &'a Doc)>, ) -> Result<Vec<Generated>, String>
Every capture file a package needs: one block_<id>.rs module per capture
block under [CAPTURE_DIR], and the main.rs that runs the block its first
argument names. Empty when no page has a capture block.
A block with a feature= tag (feature=A,B for all of them) compiles in
only under its features; without them the example exits with
[CAPTURE_DISABLED], so a capture run can keep the recorded output rather
than splice in nothing. A block keeps its own top-level fn main, whatever
it returns or however it is attributed (#[tokio::main]); a block without
one becomes the body of one. An error names a page whose block uses a
crate-level attribute, which a module cannot carry, or two pages whose
paths sanitize to the same block ids.
doc_test_set function#
pub fn doc_test_set<'a>( docs: impl IntoIterator<Item = (&'a str, &'a Doc)>, ) -> Result<Vec<Generated>, String>
Every doc-test file a package needs: one module per page with testable
blocks under [DOC_TESTS_DIR], and the main.rs that declares them.
Empty when no page has a testable block. An error names two pages whose
paths sanitize to the same module.
owning_target function#
pub fn owning_target(rel_path: &str) -> Option<(&'static str, bool)>
For rel_path (relative to the package directory) in a place gen-tests
writes, per [OWNED]: the target directory it belongs to, and whether it is
a leftover of the layout that target replaced. The file's header decides
ownership.
recorded_source function#
pub fn recorded_source(content: &str) -> Option<(&str, Option<usize>)>
The page a generated file was generated from, and the line of the block
when it is one block's file, read from its // source: PAGE[ line N] line.
sanitized_stem function#
pub fn sanitized_stem(rel_path: &str) -> String
docs/measuring.md → soothfast_doc_docs_measuring.
test_file function#
pub fn test_file(rel_path: &str, doc: &Doc) -> Option<String>
Module content for one markdown page's doc tests, or None when it has no testable blocks (all ignored / non-rust / capture).
soothfast_docs::lockfile#
Binds type_alias#
pub type Binds = BTreeMap<String, String>
item path → fingerprint (hex).
LOCKFILE constant#
pub const LOCKFILE: &str = "soothfast.lock"
Lockfile name, resolved relative to the workspace root.
Lock struct#
pub struct Lock { pub version: u64, pub binds: Binds }
Accepted binds, and the format version they were written under.
VERSION constant#
pub const VERSION: u64 = 2
Current lockfile format. Bumped whenever the fingerprint input changes, so a lock written by an older release reports as needing one re-accept rather than as prose that drifted.
comparable function#
pub fn comparable(lock: Lock) -> Result<Binds, String>
The entries of lock a fresh accept may merge over.
Fingerprints from an older format are not comparable to what this build
derives, so they are dropped rather than carried under a stamp claiming
they are current; their pages read as unlocked until their own
docs accept runs, which is what lets a repo migrate one accept at a
time.
A lock from a newer format is equally incomparable but is not this build's to discard, so it is refused instead. The asymmetry is the point: an older entry is worthless, a newer one is someone else's valid work. Accepting is deliberately stricter than checking here: a check against a newer lock only misreports, while an accept would overwrite it.
merge function#
pub fn merge(existing: &Binds, fresh: &Binds, full_scope: bool) -> Binds
Merge freshly accepted binds over existing. A full-scope accept replaces
the map outright, dropping binds that no longer exist anywhere; a partial
(explicit-paths) accept must preserve out-of-scope entries.
read function#
pub fn read(root: &Path) -> Result<Lock, String>
Read root's lockfile. A missing file is an empty map at the current
version, not an error (a fresh repo has accepted nothing yet). A file
without a version key predates the field and reads as v1.
write function#
pub fn write(root: &Path, binds: &Binds) -> Result<(), String>
Persist binds to root's lockfile as stable, pretty-printed JSON.
soothfast_docs::markdown#
Bind struct#
pub struct Bind { pub item: String, pub line: usize }
<!-- soothfast:bind path::to::item -->
ClaimMarker struct#
pub struct ClaimMarker { pub expr: String, pub line: usize }
<!-- soothfast:claim item.backend.metric < value -->
CodeBlock struct#
pub struct CodeBlock { pub index: usize, pub lang: String, pub tags: Vec<String>, pub code: String, pub line: usize, pub close_line: usize, pub ticks: usize }
One fenced code block.
Doc struct#
pub struct Doc { pub blocks: Vec<CodeBlock>, pub binds: Vec<Bind>, pub claims: Vec<ClaimMarker> }
Everything [scan] extracts from one markdown file: fenced code blocks
plus soothfast:bind / soothfast:claim markers, in document order.
scan function#
pub fn scan(text: &str) -> Result<Doc, String>
Scan one markdown text. Closing markers (<!-- /soothfast:... -->) are
structural for readers and ignored here. Errs on an unclosed fence:
dropping it would silently swallow the block and every later marker.
splice_output function#
pub fn splice_output( text: &str, nth_capture: usize, output: &str, ) -> Result<Option<String>, String>
Replace (or insert) the text soothfast-output fence that follows the
nth capture-output block (0-based among capture blocks). Ok(None) when
the capture block wasn't found; Err on malformed markdown.
soothfast_docs::markdown::CodeBlock#
feature_list function#
pub fn feature_list(&self) -> Vec<&str>
Individual features of a feature= tag — one, or several
comma-separated with no spaces (feature=risk,polygon; a space
would split into a separate fence tag) when a block needs more than one
feature to compile. Empty when the block has no feature= tag; scan
rejects a tag whose value names no feature.
soothfast_docs::reference#
render function#
pub fn render( crate_name: &str, surface: &Surface, docs_text: &BTreeMap<String, String>, baseline: &Value, ) -> String
Render one crate's surface as a markdown fragment (module-grouped).
baseline supplies measurements and assertion verdicts; pass Value::Null
to render signatures + docs only.
resolve_reference_links function#
pub fn resolve_reference_links(text: &str) -> String
Rustdoc comments often disambiguate intra-doc links with a reference-style
definition ([`Foo::bar`]: crate::Foo::bar); the site's markdown
renderer only supports inline links. Drop each definition line and inline
it into the shorthand [Foo::bar] references it defines. Doesn't handle
the separate [text][label] reference form — not seen in practice here.
soothfast_docs::surface#
ItemGroup struct#
pub struct ItemGroup<'a> { pub representative: &'a String, pub aliases: Vec<&'a String> }
One distinct item, grouped by (kind, fingerprint) to collapse the extra
path keys alias_reexports adds for the same underlying function —
representative is the shortest path (for display), aliases holds
every spelling (for lookups, since a covers= tag may name any of them).
Un-fingerprinted items (span unreadable) are never merged with others.
ItemInfo struct#
pub struct ItemInfo { pub kind: String, pub fingerprint: u64, pub signature: String, pub has_docs: bool }
What the surface records about one public item — enough to detect any change to it (fingerprint), classify the change (signature), and audit coverage (kind, has_docs).
Surface struct#
pub struct Surface { pub items: BTreeMap<String, ItemInfo> }
Public items keyed by full path (crate::module::item).
from_rustdoc function#
pub fn from_rustdoc(doc: &Value, source_root: &Path) -> Surface
Build a surface from a rustdoc JSON document. source_root resolves the
relative filenames in spans (the directory rustdoc ran in).