@@ -9,9 +9,9 @@ use std::mem;
99use std:: ops:: Deref ;
1010use std:: ptr;
1111
12- use super :: { Decoder , Encoder , Env , Error , NifResult , Term } ;
12+ use super :: { Binary , Decoder , Encoder , Env , Error , NifResult , Term } ;
1313use crate :: wrapper:: {
14- c_void, NifResourceFlags , MUTABLE_NIF_RESOURCE_HANDLE , NIF_ENV , NIF_RESOURCE_TYPE ,
14+ c_void, resource , NifResourceFlags , MUTABLE_NIF_RESOURCE_HANDLE , NIF_ENV , NIF_RESOURCE_TYPE ,
1515} ;
1616
1717/// Re-export a type used by the `resource!` macro.
@@ -78,7 +78,7 @@ pub fn open_struct_resource_type<T: ResourceTypeProvider>(
7878 flags : NifResourceFlags ,
7979) -> Option < ResourceType < T > > {
8080 let res: Option < NIF_RESOURCE_TYPE > = unsafe {
81- crate :: wrapper :: resource:: open_resource_type (
81+ resource:: open_resource_type (
8282 env. as_c_arg ( ) ,
8383 name. as_bytes ( ) ,
8484 Some ( resource_destructor :: < T > ) ,
@@ -133,8 +133,7 @@ where
133133 /// ResourceTypeProvider implemented for it. See module documentation for info on this.
134134 pub fn new ( data : T ) -> Self {
135135 let alloc_size = get_alloc_size_struct :: < T > ( ) ;
136- let mem_raw =
137- unsafe { crate :: wrapper:: resource:: alloc_resource ( T :: get_type ( ) . res , alloc_size) } ;
136+ let mem_raw = unsafe { resource:: alloc_resource ( T :: get_type ( ) . res , alloc_size) } ;
138137 let aligned_mem = unsafe { align_alloced_mem_for_struct :: < T > ( mem_raw) as * mut T } ;
139138
140139 unsafe { ptr:: write ( aligned_mem, data) } ;
@@ -145,9 +144,49 @@ where
145144 }
146145 }
147146
147+ /// Make a resource binary associated with the given resource
148+ ///
149+ /// The closure `f` is called with the referenced object and must return a slice with the same
150+ /// lifetime as the object. This means that the slice either has to be derived directly from
151+ /// the instance or that it has to have static lifetime.
152+ pub fn make_binary < ' env , ' a , F > ( & self , env : Env < ' env > , f : F ) -> Binary < ' env >
153+ where
154+ F : FnOnce ( & ' a T ) -> & ' a [ u8 ] ,
155+ {
156+ // This call is safe because `f` can only return a slice that lives at least as long as
157+ // the given instance of `T`.
158+ unsafe { self . make_binary_unsafe ( env, f) }
159+ }
160+
161+ /// Make a resource binary without strict lifetime checking
162+ ///
163+ /// The user *must* ensure that the lifetime of the returned slice is at least as long as the
164+ /// lifetime of the referenced instance.
165+ ///
166+ /// # Safety
167+ ///
168+ /// This function is only safe if the slice that is returned from the closure is guaranteed to
169+ /// live at least as long as the `ResourceArc` instance. If in doubt, use the safe version
170+ /// `ResourceArc::make_binary` which enforces this bound through its signature.
171+ pub unsafe fn make_binary_unsafe < ' env , ' a , ' b , F > ( & self , env : Env < ' env > , f : F ) -> Binary < ' env >
172+ where
173+ F : FnOnce ( & ' a T ) -> & ' b [ u8 ] ,
174+ {
175+ let bin = f ( & * self . inner ) ;
176+ let binary = rustler_sys:: enif_make_resource_binary (
177+ env. as_c_arg ( ) ,
178+ self . raw ,
179+ bin. as_ptr ( ) as * const c_void ,
180+ bin. len ( ) ,
181+ ) ;
182+
183+ let term = Term :: new ( env, binary) ;
184+ Binary :: from_term_and_slice ( term, bin)
185+ }
186+
148187 fn from_term ( term : Term ) -> Result < Self , Error > {
149188 let res_resource = match unsafe {
150- crate :: wrapper :: resource:: get_resource (
189+ resource:: get_resource (
151190 term. get_env ( ) . as_c_arg ( ) ,
152191 term. as_c_arg ( ) ,
153192 T :: get_type ( ) . res ,
@@ -157,7 +196,7 @@ where
157196 None => return Err ( Error :: BadArg ) ,
158197 } ;
159198 unsafe {
160- crate :: wrapper :: resource:: keep_resource ( res_resource) ;
199+ resource:: keep_resource ( res_resource) ;
161200 }
162201 let casted_ptr = unsafe { align_alloced_mem_for_struct :: < T > ( res_resource) as * mut T } ;
163202 Ok ( ResourceArc {
@@ -167,12 +206,7 @@ where
167206 }
168207
169208 fn as_term < ' a > ( & self , env : Env < ' a > ) -> Term < ' a > {
170- unsafe {
171- Term :: new (
172- env,
173- crate :: wrapper:: resource:: make_resource ( env. as_c_arg ( ) , self . raw ) ,
174- )
175- }
209+ unsafe { Term :: new ( env, resource:: make_resource ( env. as_c_arg ( ) , self . raw ) ) }
176210 }
177211
178212 fn as_c_arg ( & mut self ) -> * const c_void {
@@ -203,7 +237,7 @@ where
203237 /// resource. The `T` value is not cloned.
204238 fn clone ( & self ) -> Self {
205239 unsafe {
206- crate :: wrapper :: resource:: keep_resource ( self . raw ) ;
240+ resource:: keep_resource ( self . raw ) ;
207241 }
208242 ResourceArc {
209243 raw : self . raw ,
0 commit comments