Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

API Reference

First Principle

gerc is the Rust lowering and emission layer of the toolchain.

The safest downstream posture is:

  1. prefer crate-root APIs first
  2. provide gerc’s own source/evidence inputs directly
  3. keep upstream artifact translation outside gerc/src/**
  4. treat emitted Rust and build artifacts as the product boundary

API Tiers

gerc organizes its public API into two tiers:

  • Tier 1: generate(), generate_from_source(), GercConfig, GercInput, GercOutput, GercOutputMeta, SCHEMA_VERSION
  • Tier 2: the individual modules (lower, gate, emit, typemap, linkgen, crategen, consumer, c)

The crate root also re-exports the common emission entrypoints so downstream code does not need to import emit or crategen directly for routine use: emit_source, emit_type, emit_crate, emit_build_rs, emit_rustc_args, emit_rustc_link_args, OutputMode, OverwritePolicy, CrateManifest, and EmittedCrate.

For explicit staged workflows, the crate root also re-exports:

  • EvidenceInputs
  • GateDecision
  • output_meta, meta_to_json, meta_from_json, projection_to_json, and projection_from_json
  • GercConsumer, ConsumerReport, ConsumerFinding, FindingKind, PassthroughConsumer, FolConsumer, build_sidecar, sidecar_to_json, sidecar_from_json, extern_function_names, record_names, and type_alias_names

For staged inspection, import the modules explicitly:

  • gerc::gate::gate_package(...)
  • gerc::lower::lower_package(...)

The root also re-exports many gerc::c::* types directly, because the crate still supports staged and compatibility-style workflows over its own binding model.

Preferred Public Surface

These are the main consumer-facing entrypoints:

  • generate() and generate_from_source()
  • GercInput, GercConfig, and GercOutput
  • emit_source(), emit_crate(), emit_build_rs(), and emit_rustc_args()
  • JSON metadata and projection helpers
  • consumer-sidecar helpers

Primary Workflow

generate_from_source() is the preferred entrypoint when the caller already has a SourcePackage. Use GercInput directly when attaching optional translated evidence in parallel with source.

#![allow(unused)]
fn main() {
use gerc::{
    emit_crate, emit_rustc_args, emit_source, generate, generate_from_source, GercConfig,
    GercInput, OutputMode, OverwritePolicy,
};

let input = GercInput::from_source_package(source.clone())
    .with_analysis(analysis)
    .with_validation(validation)
    .with_link_plan(plan);

let output = generate_from_source(source, &GercConfig::new("mylib_sys")).unwrap();

let config = GercConfig::new("mylib_sys");
let output = generate(&input, &config).unwrap();

let source = emit_source(&output.projection);
let rustc_args = emit_rustc_args(&output.projection);
let emitted = emit_crate(
    &output.projection,
    &config,
    std::path::Path::new("/tmp/mylib_sys"),
    OutputMode::Crate,
    OverwritePolicy::Overwrite,
).unwrap();
}

GercInput also exposes from_source_json(...) for explicit JSON intake.

When validation evidence is attached, generate() filters out declarations that fail validation gating instead of emitting speculative Rust bindings.

For lower-level staged work, the public API still supports:

  • BindingPackage
  • BindingItem
  • BindingType
  • gate::gate_package(...)
  • lower::lower_package(...)

The emitted crate path supports both:

  • Cargo build-script rendering via build.rs
  • direct rustc argument rendering via rustc-link-args.txt and emit_rustc_args(...)

Downstream Posture

If you are integrating gerc into another tool, prefer:

  1. root-level generation APIs
  2. explicit GercInput construction when evidence is available
  3. emitted Rust/build outputs rather than internal lowering modules
  4. tests/examples/harnesses for any parc or linc artifact translation

Integration Coverage

The current suite exercises realistic split-pipeline paths, not only hand-constructed packages:

  • parc -> gerc source-only generation for zlib and libpng fixtures
  • parc -> linc -> gerc generation with declared link surfaces
  • parc -> linc -> gerc generation with resolved link-plan evidence

Those paths are proved in tests and examples. They are not library-level crate dependencies.

Configuration

GercConfig controls what gets generated:

FieldDefaultDescription
crate_name"gerc_output"Name for the generated crate
crate_version"0.1.0"Version string
emit_functionstrueEmit extern "C" function declarations
emit_recordstrueEmit #[repr(C)] struct/union types
emit_enumstrueEmit enum types
emit_type_aliasestrueEmit type aliases
emit_variablestrueEmit static variable declarations
emit_constantstrueEmit constant definitions
emit_build_scripttrueEmit build.rs with link metadata

Explicit Non-Goals

The current contract does not promise:

  • parsing or preprocessing C
  • binary inspection inside gerc
  • automatic invention of missing ABI facts
  • library-level dependencies on upstream pipeline crates

Error Handling

All fallible operations return GercResult<T>, which is Result<T, GercError>.

JSON Contract

Output metadata can be serialized for downstream tooling:

#![allow(unused)]
fn main() {
use gerc::contract::{output_meta, meta_to_json};

let meta = output_meta(&config, &output);
let json = meta_to_json(&meta).unwrap();
}

The JSON includes schema_version as an artifact-shape gate. meta_from_json() rejects metadata with a schema version newer than the current build supports rather than guessing.

Consumer Contract

Downstream tools implement the GercConsumer trait:

#![allow(unused)]
fn main() {
use gerc::consumer::{GercConsumer, ConsumerReport};
use gerc::ir::RustProjection;

struct MyConsumer;

impl GercConsumer for MyConsumer {
    fn inspect(&self, proj: &RustProjection) -> ConsumerReport {
        ConsumerReport::default()
    }
}
}

A MetadataSidecar (JSON) can be generated alongside the crate for tools that do not need to parse Rust source:

#![allow(unused)]
fn main() {
use gerc::consumer::{build_sidecar, sidecar_to_json};

let sidecar = build_sidecar("mylib_sys", &output.projection);
let json = sidecar_to_json(&sidecar).unwrap();
}

Generated crate metadata and crate-level src/lib.rs markers identify the emitter as GERC.