@@ -26,6 +26,7 @@ pub struct Arg {
2626 pub ty : String ,
2727 pub nullable : bool ,
2828 pub default : Option < String > ,
29+ pub as_ref : bool ,
2930}
3031
3132#[ derive( Debug , Clone ) ]
@@ -249,12 +250,19 @@ pub fn get_return_type(output_type: &ReturnType) -> Result<Option<(String, bool)
249250}
250251
251252impl Arg {
252- pub fn new ( name : String , ty : String , nullable : bool , default : Option < String > ) -> Self {
253+ pub fn new (
254+ name : String ,
255+ ty : String ,
256+ nullable : bool ,
257+ default : Option < String > ,
258+ as_ref : bool ,
259+ ) -> Self {
253260 Self {
254261 name,
255262 ty,
256263 nullable,
257264 default,
265+ as_ref,
258266 }
259267 }
260268
@@ -268,6 +276,7 @@ impl Arg {
268276 match ty {
269277 Type :: Path ( TypePath { path, .. } ) => {
270278 let mut path = path. clone ( ) ;
279+ let mut pass_by_ref = false ;
271280 path. drop_lifetimes ( ) ;
272281
273282 let seg = path. segments . last ( ) ?;
@@ -283,16 +292,53 @@ impl Arg {
283292 None
284293 }
285294 } ) ;
295+
296+ // For for types that are `Option<&mut T>` to turn them into `Option<&T>`,
297+ // marking the Arg as as "passed by reference".
298+ let option = Some ( seg)
299+ . filter ( |seg| seg. ident == "Option" )
300+ . and_then ( |seg| {
301+ if let PathArguments :: AngleBracketed ( args) = & seg. arguments {
302+ args. args
303+ . iter ( )
304+ . find ( |arg| matches ! ( arg, GenericArgument :: Type ( _) ) )
305+ . map ( |ga| {
306+ let new_ga = match ga {
307+ GenericArgument :: Type ( ty) => {
308+ let _rtype = match ty {
309+ Type :: Reference ( r) => {
310+ let mut new_ref = r. clone ( ) ;
311+ new_ref. mutability = None ;
312+ pass_by_ref = true ;
313+ Type :: Reference ( new_ref)
314+ }
315+ _ => ty. clone ( ) ,
316+ } ;
317+ GenericArgument :: Type ( _rtype)
318+ }
319+ _ => ga. clone ( ) ,
320+ } ;
321+ new_ga. to_token_stream ( ) . to_string ( )
322+ } )
323+ } else {
324+ None
325+ }
326+ } ) ;
327+
286328 let stringified = match result {
287329 Some ( result) if is_return => result,
288- _ => path. to_token_stream ( ) . to_string ( ) ,
330+ _ => match option {
331+ Some ( result) => result,
332+ None => path. to_token_stream ( ) . to_string ( ) ,
333+ } ,
289334 } ;
290335
291336 Some ( Arg :: new (
292337 name,
293338 stringified,
294339 seg. ident == "Option" || default. is_some ( ) ,
295340 default,
341+ pass_by_ref,
296342 ) )
297343 }
298344 Type :: Reference ( ref_) => {
@@ -302,6 +348,7 @@ impl Arg {
302348 ref_. to_token_stream ( ) . to_string ( ) ,
303349 false ,
304350 default,
351+ ref_. mutability . is_some ( ) ,
305352 ) )
306353 }
307354 _ => None ,
@@ -361,14 +408,15 @@ impl Arg {
361408 let ty = self . get_type_ident ( ) ;
362409
363410 let null = self . nullable . then ( || quote ! { . allow_null( ) } ) ;
411+ let passed_by_ref = self . as_ref . then ( || quote ! { . as_ref( ) } ) ;
364412 let default = self . default . as_ref ( ) . map ( |val| {
365413 quote ! {
366414 . default ( #val)
367415 }
368416 } ) ;
369417
370418 quote ! {
371- :: ext_php_rs:: args:: Arg :: new( #name, #ty) #null #default
419+ :: ext_php_rs:: args:: Arg :: new( #name, #ty) #null #passed_by_ref # default
372420 }
373421 }
374422}
0 commit comments