Skip to content

Commit ef20458

Browse files
authored
Merge pull request #638 from rusterlium/resource-impl-attrs
Fix register resource_impl arg and add name override
2 parents 566cc7c + 58e5718 commit ef20458

File tree

4 files changed

+70
-11
lines changed

4 files changed

+70
-11
lines changed

rustler/src/resource/registration.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use std::ptr;
1717
pub struct Registration {
1818
get_type_id: fn() -> TypeId,
1919
get_type_name: fn() -> &'static str,
20+
type_name: Option<&'static str>,
2021
init: ErlNifResourceTypeInit,
2122
}
2223

@@ -60,11 +61,19 @@ impl Registration {
6061
},
6162
get_type_name: std::any::type_name::<T>,
6263
get_type_id: TypeId::of::<T>,
64+
type_name: None,
6365
}
6466
.maybe_add_destructor_callback::<T>()
6567
.maybe_add_down_callback::<T>()
6668
}
6769

70+
pub const fn with_name(self, name: &'static str) -> Self {
71+
Self {
72+
type_name: Some(name),
73+
..self
74+
}
75+
}
76+
6877
const fn maybe_add_destructor_callback<T: Resource>(self) -> Self {
6978
if T::IMPLEMENTS_DESTRUCTOR || std::mem::needs_drop::<T>() {
7079
Self {
@@ -104,7 +113,7 @@ impl Registration {
104113
}
105114

106115
let type_id = (self.get_type_id)();
107-
let type_name = (self.get_type_name)();
116+
let type_name = self.type_name.unwrap_or_else(self.get_type_name);
108117

109118
let res: Option<*const ErlNifResourceType> = unsafe {
110119
open_resource_type(

rustler_codegen/src/lib.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,15 @@ pub fn nif_untagged_enum(input: TokenStream) -> TokenStream {
456456
/// }
457457
/// ```
458458
#[proc_macro_attribute]
459-
pub fn resource_impl(_attr: TokenStream, item: TokenStream) -> TokenStream {
459+
pub fn resource_impl(args: TokenStream, item: TokenStream) -> TokenStream {
460+
let mut attributes = resource_impl::Attributes::default();
461+
462+
if !args.is_empty() {
463+
let parser = syn::meta::parser(|meta| attributes.parse(meta));
464+
465+
syn::parse_macro_input!(args with parser);
466+
}
460467
let input = syn::parse_macro_input!(item as syn::ItemImpl);
461468

462-
resource_impl::transcoder_decorator(input).into()
469+
resource_impl::transcoder_decorator(attributes, input).into()
463470
}

rustler_codegen/src/resource_impl.rs

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,39 @@
11
use proc_macro2::{Span, TokenStream};
22
use quote::quote;
33
use std::collections::HashSet;
4+
use syn::{meta::ParseNestedMeta, LitBool, LitStr};
45

5-
pub fn transcoder_decorator(mut input: syn::ItemImpl) -> TokenStream {
6+
pub struct Attributes {
7+
register: bool,
8+
name: Option<String>,
9+
}
10+
11+
impl Default for Attributes {
12+
fn default() -> Self {
13+
Self {
14+
register: true,
15+
name: None,
16+
}
17+
}
18+
}
19+
20+
impl Attributes {
21+
pub fn parse(&mut self, meta: ParseNestedMeta) -> syn::parse::Result<()> {
22+
if meta.path.is_ident("register") {
23+
let value: LitBool = meta.value()?.parse()?;
24+
self.register = value.value;
25+
Ok(())
26+
} else if meta.path.is_ident("name") {
27+
let value: LitStr = meta.value()?.parse()?;
28+
self.name = Some(value.value());
29+
Ok(())
30+
} else {
31+
Err(meta.error("Unsupported macro attribute. Expecting register or name."))
32+
}
33+
}
34+
}
35+
36+
pub fn transcoder_decorator(attrs: Attributes, mut input: syn::ItemImpl) -> TokenStream {
637
// Should be `Resource` but will fail somewhere else anyway if it isn't.
738
// let (_, _trait_path, _) = input.trait_.unwrap();
839
let type_path = match *input.self_ty {
@@ -32,11 +63,23 @@ pub fn transcoder_decorator(mut input: syn::ItemImpl) -> TokenStream {
3263
input.items.push(impl_item);
3364
}
3465

35-
quote!(
36-
#input
66+
let mut res = quote!(#input);
67+
68+
if attrs.register {
69+
if let Some(name) = attrs.name {
70+
res.extend(quote!(
71+
rustler::codegen_runtime::inventory::submit!(
72+
rustler::codegen_runtime::ResourceRegistration::new::<#type_path>().with_name(#name)
73+
);
74+
));
75+
} else {
76+
res.extend(quote!(
77+
rustler::codegen_runtime::inventory::submit!(
78+
rustler::codegen_runtime::ResourceRegistration::new::<#type_path>()
79+
);
80+
));
81+
}
82+
}
3783

38-
rustler::codegen_runtime::inventory::submit!(
39-
rustler::codegen_runtime::ResourceRegistration::new::<#type_path>()
40-
);
41-
)
84+
res
4285
}

rustler_tests/native/rustler_test/src/test_resource.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub struct TestMonitorResource {
1414
inner: Mutex<TestMonitorResourceInner>,
1515
}
1616

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

0 commit comments

Comments
 (0)