Skip to content
This repository has been archived by the owner on Dec 29, 2023. It is now read-only.

ErlNifBinary.data should be *mut u8 instead of *const u8 (?) #8

Closed
tatsuya6502 opened this issue Jan 7, 2016 · 4 comments · Fixed by #9
Closed

ErlNifBinary.data should be *mut u8 instead of *const u8 (?) #8

tatsuya6502 opened this issue Jan 7, 2016 · 4 comments · Fixed by #9

Comments

@tatsuya6502
Copy link
Contributor

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
@tatsuya6502
Copy link
Contributor Author

Forgot to mention about the versions:

  • Rust 1.5.0
  • Erlang/OTP 18.2.1
  • FreeBSD 10.2-RELEASE

@goertzenator
Copy link
Collaborator

I agree with you. Can you submit your change as a PR?

@tatsuya6502
Copy link
Contributor Author

Thank you for the prompt reply! I submitted the PR #9.

@goertzenator
Copy link
Collaborator

And thank you for the PR. Also, I'm pleased to see that this works on FreeBSD.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants