Crates.io | unopus |
lib.rs | unopus |
version | 0.0.1 |
source | src |
created_at | 2024-06-14 06:23:59.774839 |
updated_at | 2024-06-14 06:23:59.774839 |
description | libopus transpiled to rust by c2rust |
homepage | |
repository | https://github.com/twlite/unopus |
max_upload_size | |
id | 1271719 |
size | 2,231,838 |
This library is libopus 1.3.1 translated from C to unsafe Rust with the assistance of c2rust.
It is called "unsafe" libopus, because it still pretty much has the same shape as the C code and is full of "unsafe".
This translation still allows you to get rid of C compiler toolchain and use the library in a pure rust environment, without linker hackery & dynamic linking issues.
It also may potentially be a starting point for a more idiomatic rust implementation of libopus, though I am not sure if it is worth the effort.
You can leverate this library by using a fork of opus
crate from this PR:
[dependencies]
opus = { git = "https://github.com/DCNick3/opus-rs.git", branch = "unsafe-libopus", default-features = false, features = ["unsafe-libopus-backend"] }
Maybe, this library will have the safe APIs in the future, but for now, it is a (mostly) drop-in replacement for the audiopus_sys
crate.
Firstly, the libopus 1.3.1 was compiled with the following commands:
CC=clang ./configure --disable-shared --disable-stack-protector --enable-extra-programs --disable-doc --disable-asm --disable-rtcd --disable-intrinsics --disable-dependency-tracking--disable-maintainer-mode --enable-hardening
CC=clang compiledb make -j
Then, using the resulting compile_commands.json
file, the C code was transpiled to rust with:
c2rust transpile compile_commands.json -o . --overwrite-existing --reorganize-definitions --emit-modules --translate-const-macros --emit-build-files
The resulting code was then manually reorganized, to remove all duplication of structures & eradicate the use of #[no_mangle] extern "C"
functions: they are all linked with rust now and do not have to exported.
Some other refactorings include:
libc::c_int
-> i32
, etc)opus_*_ctl
family of functions into macrosThe library was translated without the use of inline assembly, processor intrinsics and runtime CPU detection, so it is not as fast as the original code right now. The C version with those features is about 20% faster than the rust version on my machine.
This library is tested using (most of) the original tests from the C codebase. They are present in form of rust integration tests in the tests
directory.
The opus test vectors are also used to test the library decoder in CI (see the src/bin/run_vectors.rs
). This pretty much ensures that the decoder is correct. This actually helped uncover a subtle bug in c2rust.
The correctness of the encoder is a bit more of an open question, as there are no test vectors for it, AFAIK. There is some testing going on in tests/opus_encode
, but it's quite limited.
As for the safety, no guarantees are made. The code is a result of a pretty direct transpilation of the C code, so it is almost entirely consists of unsafe code (in rust terms).
It also seems to have UB according to miri, but those are probably false positives. A good refactoring goal might be to make the library pass miri checks.