Docker image ⏐ Quickstart ⏐ Expected C project structure ⏐ Translated Rust structure
OpenRouter models ⏐ OpenAI models ⏐ Locally-hosted models
C/Rust equivalence test generation ⏐ Citation ⏐ Acknowledgments
Note
IDEAS is under active development and may go through major changes with each release. If you encounter any obstacles, please do not hesitate to open a GitHub issue.
Run make docker/build to build the IDEAS Docker image.
All translation steps run inside this image.
For local development users must first ensure rustup is installed on their machine and available on PATH.
Run
sudo make install-sys
make install-userTo install all other required depedencies. Developed and tested on Ubuntu 24.04.
To translate a C project to a Rust workspace:
- Ensure it uses CMake as a build system.
- Place its top-level
CMakeLists.txtin theexamples/<your-project-name>/test_casefolder. - Obtain an OpenRouter API key.
And trigger end-to-end translation using the Docker image:
make examples/<your-project-name>/translate OPENROUTER_API_KEY="your-key"To run translation on a C project folder, it must be copied to the top-level examples folder.
IDEAS requires the official DARPA TRACTOR folder structure for the C projects that will be translated:
📦IDEAS
┣ 📂src/ideas # Core library
┗ 📂examples # Project folders go here
┣ 📂your-project-name
┃ ┣ 📂test_case
┃ ┃ ┣ 📂some-folder
┃ ┃ ┣ 📄some-file
┃ ┃ ┗ 📄CMakeLists.txt # Must be correct and complete
┃ ┗ 📂test_vectors # Optional, must follow the TRACTOR schema
┃ ┣ 📄some-test.json
┃ ┗ 📄other-test.json
┗ 📂other-project-name
See the examples/templates folder for minimal examples on how to organize your project.
The translation tool identifies each CMake target (library or executable) and translates it to three separate Rust crates:
- a
<name>crate that holds the C FFI compatibility layer for all safe Rust symbols. - a
<name>-rscrate that holds the#![forbid(unsafe_code)]Rust translation. - a
<name>-syscrate that links the original C library throughrust-bindgenand depletes it as translation progresses.
All crates are organized as a Rust workspace in the folder given by the TRANSLATION_DIR environment variable.
For example, running
make docker
TRANSLATION_DIR="translated_rust" make examples/templates/hello_world_lib/translate OPENROUTER_API_KEY="sk-..."Will produce the following translated folder structure:
📂examples/templates/hello_world_lib
┣ 📂test_case # The original C code is not modified
┗ 📂translated_rust
┣ 📂libhello_world_lib # C FFI compatibility layer
┃ ┣ 📂src
┃ ┃ ┗ 📄lib.rs
┃ ┗ 📄Cargo.toml
┣ 📂libhello_world_lib-rs # Safe Rust translation
┃ ┣ 📂src
┃ ┃ ┗ 📄lib.rs
┃ ┗ 📄Cargo.toml
┣ 📂libhello_world_lib-sys # Rust bindings to the original C code
┃ ┣ 📂src
┃ ┃ ┣ 📄lib.c
┃ ┃ ┗ 📄lib.rs
┃ ┣ 📄build.rs
┃ ┗ 📄Cargo.toml
┣ 🗄️cache.db # Resumable translation cache
┣ 📄Cargo.lock # Workspace lockfile
┗ 📄Cargo.toml # Workspace manifest
Binary targets have a similar expected crate structure, with a main.rs present in all crates.
Note
If translation fails and exits early, the crates are not guaranteed to be in a valid state, but are still useful for debugging and contain git logs that can be inspected.
IDEAS is capable of testing Rust translations with the DARPA TRACTOR evaluation schema.
See here for more details and the exact specification for writing test vectors and cando2 runners.
Our translation framework treats OpenRouter as the default provider.
The MODEL environment variable controls which LLM will be used, and should be the model's name on OpenRouter.
IDEAS can be used with any OpenAI model by setting the PROVIDER, MODEL, and OPENAI_API_KEY variables:
TRANSLATION_DIR="translated_rust" make examples/<your-project-name>/translate \
OPENAI_API_KEY="sk-..." \
PROVIDER="openai" \
MODEL="gpt-6-astra"To use with a locally-hosted vllm endpoint, simply set PROVIDER=hosted_vllm and use the expected model name, for example:
Then, run IDEAS using:
TRANSLATION_DIR="translated_rust" make examples/<your-project-name>/translate \
PROVIDER="hosted_vllm" \
MODEL="Qwen/Qwen3.6-35B-A3B"We offer a single-command launch of locally-hosted models using their official vllm Docker images, pinned to an exact version.
Running:
make vllm/serveWill serve GLM-5.2 on your local machine using the default recipe for single-instance, 8-way GPU inference.
Consult the official vllm recipes to identify a model suitable for your local machine.
Launch the test generation agent using:
TRANSLATION_DIR=test_crates make examples/<your-project-name>/testgen \
TESTGEN_BUDGET="4.0" \
TESTGEN_STEPS=100Note the anthropic prefix is missing from MODEL and is instead set as the PROVIDER.
This is a monolithic (single-session) agent tasked with generating unit and integration tests with high branch coverage. You can consult the agent prompt here.
For every target, the agent writes two test files to the *-sys crate:
tests/collect.rs, which snapshots inputs and matching outputs from the C code intojsonfiles.tests/io.rs, which asserts recorded snapshots using Rust'sassert!andassert_eq!macros.
The full agent trajectory is logged next to them as testgen-*.log.
If you find this repository useful, please cite the following work:
@ARTICLE{11635938,
author={Cornelius, Cory and Melara, Marcela S. and Xu, Weilin and Arvinte, Marius and Momeu, Marius and He, Jingxuan and Sen, Koushik and Song, Dawn},
journal={IEEE Security & Privacy},
title={IDEAS: C-to-Rust Translation Using Improved Large Language Model Decoding and Automated Equivalence Testing},
year={2026},
volume={},
number={},
pages={2-11},
keywords={Testing;Translation;Codes;Memory;Modeling;Symbols;Feedback;Large language models;Security;Safety},
doi={10.1109/MSEC.2026.3710126}}
This material is based upon work supported by the Defense Advanced Research Projects Agency (DARPA) Translating All C To Rust (TRACTOR) program under Agreement No. HR00112590134.