Skip to main content

Crate sealmap_model

Crate sealmap_model 

Source
Expand description

§sealmap-model

A language-neutral, deterministic model of a codebase: source files, the symbols they define, and the typed relations between those symbols.

This crate is the shared vocabulary of the sealmap workspace. Language language adapters (such as sealmap-rust) produce a Codebase; projections (such as sealmap-corpus) consume one and render Mermaid diagrams from it. Because both sides only meet here, you can add a language adapter for another language, or a new diagram projection, without touching the other half.

The navigation API is loosely inspired by ts-morph (MIT, © David Sherret): a single Codebase value you can ask for files, symbols and relations, with an in-memory SourceSet standing in for the file system so tests and embedders never need to touch disk.

§Determinism contract

Every type in this crate upholds the following, and downstream crates rely on it to produce byte-identical output across runs, machines and operating systems:

  1. Ordered collections only. All maps and sets are BTreeMap / BTreeSet; iteration order is a function of the data, never of a hash seed or insertion order.
  2. Normalised paths. SourcePath is always relative, /-separated and free of ./.. components, so src\lib.rs on Windows and src/lib.rs on Linux are the same key.
  3. Stable hashing. ContentHash is BLAKE3 over the source text with line endings normalised to \n; it never uses std’s randomly seeded hasher.
  4. No ambient data. Nothing in the model records timestamps, absolute paths, user names or environment variables.

§Built for sequence diagrams

Callables carry a Flow: the ordered tree of calls, branches, loops and early exits in their body. That is what makes dense, per-function sequence diagrams possible without running the code, and because every call target is a canonical SymbolId, separately rendered sequences can be merged or inlined into each other by a downstream orchestrator.

§Symbol ids

Every symbol is named by a sym: id (see sym): kind-explicit, SCIP-style, with no file path, so moving code between files never changes an id. Beside the id, every symbol carries two Fingerprints: sig_hash over its contract and body_hash over its implementation, so a tool can tell “unchanged”, “behaviour changed” (body only) and “contract changed” (signature) apart, and can match a renamed symbol by its body.

§Example

Build a tiny model by hand and query it:

use sealmap_model::*;

let pkg = Package::current("cargo", "demo").unwrap();
let root = SymbolId::package_root(pkg.clone());
let id = |name: &str| root.child(Descriptor::r#type(name)).unwrap();

let mut cb = Codebase::new("demo");
let file = SourcePath::new("src/lib.rs").unwrap();
cb.add_file(SourceFile::new(file.clone(), "rust", root.clone(), "pub struct A;"));

cb.add_symbol(Symbol::new(id("A"), "A", SymbolKind::Struct, file.clone()));
cb.add_symbol(Symbol::new(id("B"), "B", SymbolKind::Struct, file.clone()));
cb.add_relation(Relation::new(id("A"), id("B"), RelationKind::FieldType, Confidence::Exact));

assert_eq!(id("A").to_string(), "sym:cargo demo . A#");
assert_eq!(cb.symbols_in_file(&file).count(), 2);
assert_eq!(cb.relations_from(&id("A")).count(), 1);

Re-exports§

pub use flow::Arm;
pub use flow::Call;
pub use flow::CallKind;
pub use flow::Exit;
pub use flow::Flow;
pub use flow::Step;
pub use sym::Descriptor;
pub use sym::DescriptorKind;
pub use sym::DescriptorView;
pub use sym::GlobalView;
pub use sym::IdError;
pub use sym::IdView;
pub use sym::Package;
pub use sym::Suffix;
pub use sym::SymbolId;
pub use sym::Version;

Modules§

flow
Ordered call/control flow of a function body: the raw material for sequence diagrams.
sym
The sym: symbol-id grammar.

Structs§

Codebase
The whole analysed codebase: files, symbols and relations.
CodebaseStats
Summary counts for a Codebase.
ContentHash
A stable, portable content hash: BLAKE3 over text with \r\n and lone \r normalised to \n.
Fingerprint
A per-symbol content fingerprint: the first 16 bytes of a BLAKE3 digest.
LoadOptions
Options for SourceSet::load_dir.
Member
A field, variant or associated item listed inside a type in structure diagrams. Methods with bodies are full Symbols instead, because they carry their own Flow and relations.
Relation
A directed, typed edge between two symbols.
SourceFile
Metadata about one analysed source file. The file’s text is not stored in the model; only its hash, so the model stays small and the corpus can detect drift.
SourcePath
A normalised, relative, /-separated path to a source file, used as the primary key for files everywhere in sealmap.
SourceSet
An in-memory set of source files keyed by SourcePath.
Span
A source range. Lines and columns are 1-based; end is inclusive of the last line containing the item.
Symbol
A named definition in the codebase.

Enums§

Confidence
How sure the language adapter is that a relation’s target is correct.
MemberKind
What a Member is.
ModelJsonError
Why Codebase::from_json refused its input.
PathError
Why a string could not become a SourcePath.
RelationKind
The kind of a directed edge between two symbols.
SymbolKind
What kind of thing a Symbol is.
Visibility
Visibility of a symbol or member.

Constants§

MODEL_SCHEMA_VERSION
Version of the serialised model schema (the JSON shape of Codebase).
PARSE_ERROR_TAG
The tag a language adapter puts on the module symbol of a file it could not parse. Such a file contributes that one symbol and nothing else, so any definition it held is missing from the model.