Rust API Reference
Rust API
Section titled “Rust API”This guide covers using the closed-source arxo-engine from Rust via the arxo-loader crate. The loader dynamically loads the engine library and exposes four operations: load, load from path, version, and analyze. Analysis returns a single JSON string that you parse to get results and policy violations.
Dependencies
Section titled “Dependencies”[dependencies]arxo-types = "0.1" # Config and shared types (MIT)arxo-loader = "0.1" # Dynamic engine loaderserde = { version = "1.0", features = ["derive"] }serde_json = "1.0" # Parse result JSONanyhow = "1.0" # Error handlingPublic API Summary
Section titled “Public API Summary”| Item | Description |
|---|---|
EngineLibrary | Handle to the loaded engine (from arxo_loader) |
EngineLibrary::load() | Load engine from default locations (env, same dir, cache, CDN) |
EngineLibrary::load_from_path(path) | Load engine from a specific library path |
engine.version() | Engine version string |
engine.analyze(path, config, license) | Run analysis; returns Result<AnalysisResult, LoadError> |
AnalysisResult | { json: String } — raw JSON from the engine |
LoadError | Load or analysis failure (NotFound, LoadFailed, InvalidSymbol, AnalyzeFailed, DownloadFailed) |
Configuration uses arxo_types::config::schema::Config. You build or deserialize Config, then pass the project path and config to analyze. Optional license can be None (engine may use env or default).
Loading the Engine
Section titled “Loading the Engine”use arxo_loader::EngineLibrary;use std::path::Path;
fn main() -> Result<(), arxo_loader::LoadError> { // Load from default locations (ARCH0_ENGINE_PATH, same dir as binary, cache, CDN) let engine = EngineLibrary::load()?;
// Or load from a specific path let engine = EngineLibrary::load_from_path(Path::new("/path/to/libarxo_engine.so"))?;
println!("Engine version: {}", engine.version()); Ok(())}Running Analysis
Section titled “Running Analysis”You pass a path (project root), a config (from arxo-types), and an optional license string. The result is an AnalysisResult with a single field json: a string containing the full result and violations as JSON.
use arxo_loader::{EngineLibrary, LoadError};use arxo_types::config::schema::Config;use std::path::Path;
fn analyze_project() -> Result<(), LoadError> { let engine = EngineLibrary::load()?; let path = Path::new("./my-project");
let config = Config { metric_preset: Some("quick".to_string()), data: None, source: None, architecture: None, metrics: None, policy: None, report: None, run_options: None, };
let result = engine.analyze(path, &config, None)?; println!("Result JSON: {}", result.json); Ok(())}Parsing the Result JSON
Section titled “Parsing the Result JSON”The engine returns a JSON object with at least results (array of metric results) and violations (array of policy violations). Parse result.json with serde_json to inspect them.
use serde::Deserialize;
#[derive(Debug, Deserialize)]struct AnalysisOutput { results: Option<Vec<MetricResultItem>>, violations: Option<Vec<ViolationItem>>,}
#[derive(Debug, Deserialize)]struct MetricResultItem { id: Option<String>, // ... other fields depend on metric}
#[derive(Debug, Deserialize)]struct ViolationItem { metric: Option<String>, message: Option<String>, // ... other fields}
fn use_result(result: &arxo_loader::AnalysisResult) -> anyhow::Result<()> { let out: AnalysisOutput = serde_json::from_str(&result.json)?; if let Some(violations) = &out.violations { for v in violations { eprintln!("Violation: {:?}", v.message); } } if let Some(results) = &out.results { for r in results { println!("Metric {}: {:?}", r.id.as_deref().unwrap_or("?"), r); } } Ok(())}Exact shape of results and violations depends on your config (metrics enabled, policy rules). Use the same schema as the engine’s JSON report or inspect a sample output.
Configuration
Section titled “Configuration”Build a Config from arxo_types::config::schema (or deserialize from YAML/JSON). Key fields include:
metric_preset— e.g."quick","ci","full"(replaces explicit metrics list when set)data— language, import_graph (exclude, group_by, group_depth), call_graph, git_history, etc.policy— rules to evaluate (metric, operator, threshold)report— format and file (engine uses this for internal reporting; your programmatic output is still the JSON string)run_options— disable_cache, incremental, quiet
See Configuration for the full schema. Minimal programmatic example (or load from YAML/JSON and deserialize):
use arxo_types::config::schema::Config;
let config = Config { source: None, data: None, architecture: None, metrics: None, metric_preset: Some("quick".to_string()), policy: None, report: None, run_options: None,};// For data options (language, exclude, etc.) build DataConfig and set config.data, or load from file.Error Handling
Section titled “Error Handling”arxo_loader uses LoadError for load and analysis failures:
use arxo_loader::{EngineLibrary, LoadError};
fn run() -> Result<(), LoadError> { use arxo_types::config::schema::Config; let engine = EngineLibrary::load()?; let config = Config { source: None, data: None, architecture: None, metrics: None, metric_preset: Some("quick".to_string()), policy: None, report: None, run_options: None, }; let result = engine.analyze(std::path::Path::new("."), &config, None)?; println!("{}", result.json); Ok(())}
fn main() { if let Err(e) = run() { eprintln!("Error: {}", e); std::process::exit(1); }}Variants: NotFound, LoadFailed, InvalidSymbol, AnalyzeFailed, DownloadFailed. Use thiserror display or match on the variant as needed.
Optional: License
Section titled “Optional: License”If your deployment requires a license, pass it as the third argument to analyze or set the ARCH0_LICENSE_KEY environment variable. Pass None to use env/default.
let license = std::env::var("ARCH0_LICENSE_KEY").ok();let result = engine.analyze(path, &config, license.as_deref())?;Helper Functions (optional)
Section titled “Helper Functions (optional)”arxo_engine_lib_name() and platform_triple() are re-exported from arxo_loader for use when resolving the engine path (e.g. for custom download or UI):
use arxo_loader::{arxo_engine_lib_name, platform_triple};
println!("Library name: {}", arxo_engine_lib_name());println!("Platform: {}", platform_triple());Best Practices
Section titled “Best Practices”- Reuse the engine — Call
EngineLibrary::load()once and run multipleanalyzecalls with different paths/configs. - Cache config — Build or load
Configonce and reuse; only change what you need per run. - Parse JSON once — Deserialize
result.jsoninto your own types and work with typed data. - Handle LoadError — Surface load/analysis failures to the user or CI (e.g. exit code, log, retry).
- Use presets — Set
metric_preset(e.g."quick") instead of building a full metrics list unless you need fine-grained control.
Next Steps
Section titled “Next Steps”- Configuration - Full config schema
- FFI API - Same engine via C symbols (other languages)
- Troubleshooting - Common issues