Skip to content

Commit

Permalink
Merge pull request #638 from rusterlium/resource-impl-attrs
Browse files Browse the repository at this point in the history
Fix register resource_impl arg and add name override
  • Loading branch information
filmor authored Jul 13, 2024
2 parents 566cc7c + 58e5718 commit ef20458
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 11 deletions.
11 changes: 10 additions & 1 deletion rustler/src/resource/registration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::ptr;
pub struct Registration {
get_type_id: fn() -> TypeId,
get_type_name: fn() -> &'static str,
type_name: Option<&'static str>,
init: ErlNifResourceTypeInit,
}

Expand Down Expand Up @@ -60,11 +61,19 @@ impl Registration {
},
get_type_name: std::any::type_name::<T>,
get_type_id: TypeId::of::<T>,
type_name: None,
}
.maybe_add_destructor_callback::<T>()
.maybe_add_down_callback::<T>()
}

pub const fn with_name(self, name: &'static str) -> Self {
Self {
type_name: Some(name),
..self
}
}

const fn maybe_add_destructor_callback<T: Resource>(self) -> Self {
if T::IMPLEMENTS_DESTRUCTOR || std::mem::needs_drop::<T>() {
Self {
Expand Down Expand Up @@ -104,7 +113,7 @@ impl Registration {
}

let type_id = (self.get_type_id)();
let type_name = (self.get_type_name)();
let type_name = self.type_name.unwrap_or_else(self.get_type_name);

let res: Option<*const ErlNifResourceType> = unsafe {
open_resource_type(
Expand Down
11 changes: 9 additions & 2 deletions rustler_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,15 @@ pub fn nif_untagged_enum(input: TokenStream) -> TokenStream {
/// }
/// ```
#[proc_macro_attribute]
pub fn resource_impl(_attr: TokenStream, item: TokenStream) -> TokenStream {
pub fn resource_impl(args: TokenStream, item: TokenStream) -> TokenStream {
let mut attributes = resource_impl::Attributes::default();

if !args.is_empty() {
let parser = syn::meta::parser(|meta| attributes.parse(meta));

syn::parse_macro_input!(args with parser);
}
let input = syn::parse_macro_input!(item as syn::ItemImpl);

resource_impl::transcoder_decorator(input).into()
resource_impl::transcoder_decorator(attributes, input).into()
}
57 changes: 50 additions & 7 deletions rustler_codegen/src/resource_impl.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,39 @@
use proc_macro2::{Span, TokenStream};
use quote::quote;
use std::collections::HashSet;
use syn::{meta::ParseNestedMeta, LitBool, LitStr};

pub fn transcoder_decorator(mut input: syn::ItemImpl) -> TokenStream {
pub struct Attributes {
register: bool,
name: Option<String>,
}

impl Default for Attributes {
fn default() -> Self {
Self {
register: true,
name: None,
}
}
}

impl Attributes {
pub fn parse(&mut self, meta: ParseNestedMeta) -> syn::parse::Result<()> {
if meta.path.is_ident("register") {
let value: LitBool = meta.value()?.parse()?;
self.register = value.value;
Ok(())
} else if meta.path.is_ident("name") {
let value: LitStr = meta.value()?.parse()?;
self.name = Some(value.value());
Ok(())
} else {
Err(meta.error("Unsupported macro attribute. Expecting register or name."))
}
}
}

pub fn transcoder_decorator(attrs: Attributes, mut input: syn::ItemImpl) -> TokenStream {
// Should be `Resource` but will fail somewhere else anyway if it isn't.
// let (_, _trait_path, _) = input.trait_.unwrap();
let type_path = match *input.self_ty {
Expand Down Expand Up @@ -32,11 +63,23 @@ pub fn transcoder_decorator(mut input: syn::ItemImpl) -> TokenStream {
input.items.push(impl_item);
}

quote!(
#input
let mut res = quote!(#input);

if attrs.register {
if let Some(name) = attrs.name {
res.extend(quote!(
rustler::codegen_runtime::inventory::submit!(
rustler::codegen_runtime::ResourceRegistration::new::<#type_path>().with_name(#name)
);
));
} else {
res.extend(quote!(
rustler::codegen_runtime::inventory::submit!(
rustler::codegen_runtime::ResourceRegistration::new::<#type_path>()
);
));
}
}

rustler::codegen_runtime::inventory::submit!(
rustler::codegen_runtime::ResourceRegistration::new::<#type_path>()
);
)
res
}
2 changes: 1 addition & 1 deletion rustler_tests/native/rustler_test/src/test_resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct TestMonitorResource {
inner: Mutex<TestMonitorResourceInner>,
}

#[rustler::resource_impl(register = true)]
#[rustler::resource_impl(register = true, name = "monitor")]
impl Resource for TestMonitorResource {
fn down<'a>(&'a self, _env: Env<'a>, _pid: LocalPid, mon: Monitor) {
let mut inner = self.inner.lock().unwrap();
Expand Down

0 comments on commit ef20458

Please sign in to comment.