ErlNifBinary.data should be *mut u8 instead of *const u8 (?)
tatsuya6502 opened this issue · 4 comments
I am trying to port vinoski/bitwise NIF examples to Rust, but I found that Rust compiler does not let me update the contents of the data
field of ErlNifBinary
.
I am not totally sure as I just started to play with Rust a few days ago, but it looks like the data
field should be defined as *mut u8
instead of *const u8
?
ruster_unsafe/src/lib.rs
pub struct ErlNifBinary {
pub size: size_t,
pub data: *const u8,
bin_term: ERL_NIF_TERM,
ref_bin: *mut c_void,
}
Here is relevant code from my program. (Ported from bitwise_nif.c#L14-L38)
/// Erlang: -spec exor(binary(), byte::0..255) -> binary().
///
/// exor misbehaves on a regular scheduler thread when the incomng binary is
/// large because it blocks the thread for too long. But it works fine on a
/// dirty scheduler.
extern "C" fn exor(env: *mut ErlNifEnv,
argc: c_int,
args: *const ERL_NIF_TERM) -> ERL_NIF_TERM {
unsafe {
let mut bin: ErlNifBinary = uninitialized();
let mut outbin: ErlNifBinary = uninitialized();
let mut val: c_uint = uninitialized();
if argc != 2
|| 0 == enif_inspect_binary(env, *args, &mut bin)
|| 0 == enif_get_uint(env, *args.offset(1), &mut val)
|| val > 255 {
return enif_make_badarg(env);
}
if bin.size == 0 {
return *args;
}
enif_alloc_binary(bin.size, &mut outbin);
do_xor(bin.data, bin.size, outbin.data, val as u8); // <-- This line does not compile.
// @TODO: Implement enif_make_tuple2() and friends in ruster_unsafe
// enif_make_tuple2(env,
// enif_make_binary(env, &mut outbin),
// enif_make_int(env, 0))
enif_make_binary(env, &mut outbin)
}
}
fn do_xor(bin_data: *const u8, length: usize, outbin_data: *mut u8, byte: u8) {
let bin_slice: &[u8] = unsafe {slice::from_raw_parts(bin_data, length)};
let outbin_slice: &mut[u8] = unsafe {slice::from_raw_parts_mut(outbin_data, length)};
for (b, ob) in bin_slice.iter().zip(outbin_slice.iter_mut()) {
(*ob) = (*b) ^ byte;
}
}
And the compile error:
src/lib.rs:75:36: 75:47 error: mismatched types:
expected `*mut u8`,
found `*const u8`
(values differ in mutability) [E0308]
src/lib.rs:75 do_xor(bin.data, bin.size, outbin.data, val as u8);
^~~~~~~~~~~
src/lib.rs:75:36: 75:47 help: run `rustc --explain E0308` to see a detailed explanation
error: aborting due to previous error
Could not compile `bitwise_rust_erlang`.
If I change the data
field to *mut u8
, it will compile.
% cargo build --release
Compiling libc v0.2.4
Compiling ruster_unsafe v0.2.0 (https://github.com/tatsuya6502/ruster_unsafe/?rev=nif-2.9#2f68285f)
Compiling bitwise_rust_erlang v0.1.0 (file:///usr/home/tatsuya/workhub/dev/bitwise-rust-erlang)
% ls -lh target/release/lib*.so
-rwxr-xr-x 1 tatsuya tatsuya 2.0M Jan 7 21:36 target/release/libbitwise_nif.so
Forgot to mention about the versions:
- Rust 1.5.0
- Erlang/OTP 18.2.1
- FreeBSD 10.2-RELEASE
I agree with you. Can you submit your change as a PR?
Thank you for the prompt reply! I submitted the PR #9.
And thank you for the PR. Also, I'm pleased to see that this works on FreeBSD.