CCARP - (trans)Compile C And Rust Partially
CCARP is a command line utility made with the sole purpose of transcompiling or transpiling C programs into Rust.
Does it actually work?
Somewhat.
At the moment CCARP can be used to rustify simple C programs, but for more complex programs it will most likely run into an error. If it succeeds however, it will produce a Rust program which either compiles or almost compiles, in either way its meaning will be similar to the C code (if one manages to solve all conflicts within the generated code).
An example
Example C code:
int
int
Generated Rust code (after formatting and simplification):
How to use it?
CCARP can be both a library and an executable.
You can use it as a dependency
in this case translate, translate_single_file and translate_project functions are available.
Or alternatively you can install it as an executable via
After that a
command will show you how it can be used.
What does CCARP implement from C?
CCARP mainly implements the core of C, as in the syntax approximate meaning of C without most macros and standard library. (Also without goto, labels and variadic functions amongst other things.)
What will most likely work:
- standard primitive types (
char,short,int,long,long long, etc.) - expressions with primitive types (e.g.
1 + 2,a + b,1 ? a << 2 : b & c * 2) - fixed size arrays (
int arr[5],{1,2,3}) - simple declarations (
int c=0;,typedef int int32;) - most statements
if (1==2) { a=1; } else { a=2; }for (int i=0;i<10;i++) { a+=2; }while (a<5) { a++; }
- switch with some restrictions
switch
in general:
switch
- function definitions (
int add_two(int n) { return n+2; })
How does CCARP deal with types?
Primitive types
Primitive types are translated to the following Rust types:
| c type | rust type |
|---|---|
| char | u8 |
| unsigned char | u8 |
| signed char | i8 |
| short | i16 |
| unsigned short | u16 |
| int | i32 |
| unsigned int | u32 |
| long | i64 |
| unsigned long | u64 |
| long long | i64 |
| unsigned long long | u64 |
| float | f32 |
| double | f64 |
| long double | f64 |
| bool | ~i8 |
| void | () |
Arrays and Pointers
Arrays and pointers are somewhat dependent on compiler flags in translation. Basic array and pointer types:
| c type | rust type |
|---|---|
| int * | *mut i32 |
| const int * | *const i32 |
| int *const | &mut i32 |
| const int *const | &i32 |
| int arr[N] | [i32;N] |
Conversions
CCARP applies a best-effort conversion between types, but not all types can be trivially converted into another. This is why for example void * does not compile to valid Rust at the moment.
How does CCARP work?
CCARP uses Pest for parsing its inputs into tokens; after tokenisation it parses tokens into C translation units and creates a C AST (Abstract Syntax Tree for short) from it; the next step after that is logically morphing the C AST into a Rust AST and from that the program can produce a Rust code (which might or might not work).
In fewer words:
- C Code
- Tokenisation
- Parsing tokens into structures
- C AST
- Rust AST
- Rust Code