diff --git a/CHANGELOG.md b/CHANGELOG.md index 34a89324..cdb89d49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ versions. ### Changed +- Adjust C char types to use the proper FFI type (#592) +- Allow arbitrary (ASCII) NIF function names (#593, idea and initial + implementation by @KoviRobi) + ### Removed ## [0.31.0] - 2024-02-13 diff --git a/rustler_codegen/src/nif.rs b/rustler_codegen/src/nif.rs index 27df49a6..a0f53a5b 100644 --- a/rustler_codegen/src/nif.rs +++ b/rustler_codegen/src/nif.rs @@ -48,15 +48,18 @@ pub fn transcoder_decorator(nif_attributes: NifAttributes, fun: syn::ItemFn) -> let argument_names = create_function_params(inputs.clone()); let erl_func_name = nif_attributes .custom_name - .map(|n| syn::Ident::new(n.value().as_str(), Span::call_site())) - .unwrap_or_else(|| name.clone()); + .map_or_else(|| name.to_string(), |n| n.value().to_string()); + + if !erl_func_name.is_ascii() || erl_func_name.chars().any(|x| x.is_ascii_control()) { + panic!("Only non-Control ASCII strings are supported as function names"); + } quote! { #[allow(non_camel_case_types)] pub struct #name; impl rustler::Nif for #name { - const NAME: *const rustler::codegen_runtime::c_char = concat!(stringify!(#erl_func_name), "\0").as_ptr() as *const rustler::codegen_runtime::c_char; + const NAME: *const rustler::codegen_runtime::c_char = concat!(#erl_func_name, "\0").as_ptr() as *const rustler::codegen_runtime::c_char; const ARITY: rustler::codegen_runtime::c_uint = #arity; const FLAGS: rustler::codegen_runtime::c_uint = #flags as rustler::codegen_runtime::c_uint; const RAW_FUNC: unsafe extern "C" fn( diff --git a/rustler_tests/lib/rustler_test.ex b/rustler_tests/lib/rustler_test.ex index 1adaded7..ce424d40 100644 --- a/rustler_tests/lib/rustler_test.ex +++ b/rustler_tests/lib/rustler_test.ex @@ -121,7 +121,7 @@ defmodule RustlerTest do def raise_term_with_atom_error(), do: err() def term_with_tuple_error(), do: err() - def nif_attrs_can_rename(), do: err() + def nif_attrs_can_rename!(), do: err() def add_from_tuple(_tuple), do: err() def add_one_to_tuple(_tuple), do: err() diff --git a/rustler_tests/native/rustler_test/src/test_nif_attrs.rs b/rustler_tests/native/rustler_test/src/test_nif_attrs.rs index 1c40c22c..e992d0b8 100644 --- a/rustler_tests/native/rustler_test/src/test_nif_attrs.rs +++ b/rustler_tests/native/rustler_test/src/test_nif_attrs.rs @@ -1,4 +1,4 @@ -#[rustler::nif(name = "nif_attrs_can_rename")] +#[rustler::nif(name = "nif_attrs_can_rename!")] pub fn can_rename() -> bool { true } diff --git a/rustler_tests/test/nif_attrs_test.exs b/rustler_tests/test/nif_attrs_test.exs index 1e916c91..6805436e 100644 --- a/rustler_tests/test/nif_attrs_test.exs +++ b/rustler_tests/test/nif_attrs_test.exs @@ -2,6 +2,6 @@ defmodule NifAttrsTest do use ExUnit.Case test "can rename a NIF with an attribute" do - assert RustlerTest.nif_attrs_can_rename() + assert RustlerTest.nif_attrs_can_rename!() end end