Expand description
canton-codegen — generate typed Rust bindings from Daml packages.
This crate turns a DAR into idiomatic Rust: templates and records into
structs, choices into typed exercise impls, interfaces into typed markers
with views, with JSON and gRPC codecs on every generated type. The
command-line front-end is canton-codegen-cli (dpm codegen-rust); most
users drive codegen through that.
§Usage
lower_dar turns a .dar into the ir, and generate_crate turns
that into the source of a self-contained bindings crate:
let dar = canton_lf::Dar::open("my-app-0.1.0.dar")?;
let (krate, skipped) = canton_codegen::lower_dar(&dar)?;
let source = canton_codegen::generate_crate(&krate)?;
for skip in &skipped {
eprintln!("warning: skipped {}", skip);
}
std::fs::write("src/lib.rs", source)?;§Architecture
A decoder-agnostic ir (intermediate representation) sits between
decoding Daml-LF and emitting Rust:
DAR ──(canton-lf: decode)──▶ lower ──▶ ir ──(emit/map)──▶ Rust sourceThe generator and the type mapping consume the IR and never touch Daml-LF;
lowering is the one step that reads the decoded LF AST (from canton-lf,
which is held to the official daml-lf-archive reader by a conformance
oracle). Every generator checks its output parses as valid Rust before
returning it. The IR is public so a caller can emit something other than
Rust from it, or post-process before emission; the emitter and type mapper
are private (their signatures are proc-macro2 token streams, which would
otherwise become part of this crate’s SemVer surface).
The human-readable specification of the type mapping lives in
docs/daml-lf-type-mapping.md.
Re-exports§
pub use canton_lf;
Modules§
- ir
- A decoder-agnostic intermediate representation (IR) of Daml types.
Structs§
- Codegen
Error - Emitting Rust from the
irfailed. - External
Packages - Packages to reference rather than generate, keyed by package id or package name.
- Options
- What to generate and where. Build with
Options::new, then thewith_*methods. - Selection
- Which of a DAR’s packages a crate emits.
- Skipped
Type - A declaration that could not be lowered into the IR, and why.
- Stats
- A summary of a successful generation.
Enums§
- Generate
Error - Writing a bindings crate failed.
- Runtime
- How the generated crate depends on the
canton-damlruntime.
Functions§
- default_
crate_ name - Derive a crate name from a DAR path: its file stem with the trailing
version dropped, sanitised to a valid Cargo package name
(
splice-amulet-0.1.14.dar→splice-amulet). - generate
- Decode
opts.dar, lower its whole closure, and write a bindings crate (Cargo.toml+src/lib.rs) into the output directory. - generate_
crate - Generate a whole crate’s
lib.rsfrom a lowered DAR: apub modtree (package → module → types) where every cross-module and cross-package reference resolves through its qualified path. - generate_
data_ type - Generate formatted Rust source for a named data type (record / variant / enum).
- generate_
interface - Generate formatted Rust source for an interface’s impls (its
Contract/Interfaceidentity and typed choice impls) on its marker type. - generate_
module - Generate a complete module file: the
use canton_daml as rt;preamble plus every data type and template, ready to write to a.rsfile in a generated crate. - generate_
record - Generate formatted Rust source for a single record data type.
- generate_
template - Generate formatted Rust source for a template: its payload struct plus the typed choice impls.
- lower_
dar - Lower a whole DAR (its main package and its full dependency closure) into a
Crateof qualified modules, plus the list of types that could not be lowered (best-effort: seeSkippedType). - lower_
dar_ selecting - The same, emitting only the packages a
Selectionnames. - lower_
dar_ with - The same, with packages that are already published as their own crates referenced instead of re-emitted.
- lower_
packages_ selecting - The same, from packages already decoded rather than from a DAR.