1515use crate :: {
1616 classes:: { ClassEntry , RawVisibility , Visibility } ,
1717 errors:: { throw, ArgumentCountError , ExceptionGuard , ThrowObject , Throwable } ,
18+ modules:: global_module,
1819 objects:: { StateObj , ZObj , ZObject } ,
1920 strings:: { ZStr , ZString } ,
2021 sys:: * ,
22+ types:: TypeInfo ,
2123 utils:: ensure_end_with_zero,
2224 values:: { ExecuteData , ZVal } ,
2325} ;
2426use phper_alloc:: ToRefOwned ;
2527use std:: {
28+ collections:: HashMap ,
2629 ffi:: { CStr , CString } ,
2730 marker:: PhantomData ,
28- mem:: { transmute, zeroed, ManuallyDrop } ,
31+ mem:: { size_of , transmute, zeroed, ManuallyDrop } ,
2932 ptr:: { self , null_mut} ,
3033 rc:: Rc ,
34+ slice,
3135} ;
3236
37+ /// Used to mark the arguments obtained by the invoke function as mysterious
38+ /// codes from phper
39+ const INVOKE_MYSTERIOUS_CODE : & [ u8 ] = b"PHPER" ;
40+
41+ /// Used to find the handler in the invoke function.
42+ pub ( crate ) type HandlerMap = HashMap < ( Option < CString > , CString ) , Rc < dyn Callable > > ;
43+
3344pub ( crate ) trait Callable {
3445 fn call ( & self , execute_data : & mut ExecuteData , arguments : & mut [ ZVal ] , return_value : & mut ZVal ) ;
3546}
@@ -107,6 +118,7 @@ impl FunctionEntry {
107118 Self :: entry (
108119 & entity. name ,
109120 & entity. arguments ,
121+ entity. return_type . as_ref ( ) ,
110122 Some ( entity. handler . clone ( ) ) ,
111123 None ,
112124 )
@@ -116,20 +128,31 @@ impl FunctionEntry {
116128 Self :: entry (
117129 & entity. name ,
118130 & entity. arguments ,
131+ entity. return_type . as_ref ( ) ,
119132 entity. handler . clone ( ) ,
120133 Some ( entity. visibility ) ,
121134 )
122135 }
123136
124137 /// Will leak memory
125138 unsafe fn entry (
126- name : & CStr , arguments : & [ Argument ] , handler : Option < Rc < dyn Callable > > ,
127- visibility : Option < RawVisibility > ,
139+ name : & CStr , arguments : & [ Argument ] , return_type : Option < & ReturnType > ,
140+ handler : Option < Rc < dyn Callable > > , visibility : Option < RawVisibility > ,
128141 ) -> zend_function_entry {
129142 let mut infos = Vec :: new ( ) ;
130143
131144 let require_arg_count = arguments. iter ( ) . filter ( |arg| arg. required ) . count ( ) ;
132- infos. push ( phper_zend_begin_arg_info_ex ( false , require_arg_count) ) ;
145+
146+ if let Some ( return_type) = return_type {
147+ infos. push ( phper_zend_begin_arg_with_return_type_info_ex (
148+ return_type. ret_by_ref ,
149+ require_arg_count,
150+ return_type. type_info . into_raw ( ) ,
151+ return_type. allow_null ,
152+ ) ) ;
153+ } else {
154+ infos. push ( phper_zend_begin_arg_info_ex ( false , require_arg_count) ) ;
155+ }
133156
134157 for arg in arguments {
135158 infos. push ( phper_zend_arg_info (
@@ -140,6 +163,9 @@ impl FunctionEntry {
140163
141164 infos. push ( zeroed :: < zend_internal_arg_info > ( ) ) ;
142165
166+ // Will be checked in `invoke` function.
167+ infos. push ( Self :: create_mysterious_code ( ) ) ;
168+
143169 let raw_handler = handler. as_ref ( ) . map ( |_| invoke as _ ) ;
144170
145171 if let Some ( handler) = handler {
@@ -160,13 +186,22 @@ impl FunctionEntry {
160186 flags,
161187 }
162188 }
189+
190+ unsafe fn create_mysterious_code ( ) -> zend_internal_arg_info {
191+ let mut mysterious_code = [ 0u8 ; size_of :: < zend_internal_arg_info > ( ) ] ;
192+ for ( i, n) in INVOKE_MYSTERIOUS_CODE . iter ( ) . enumerate ( ) {
193+ mysterious_code[ i] = * n;
194+ }
195+ transmute ( mysterious_code)
196+ }
163197}
164198
165199/// Builder for registering php function.
166200pub struct FunctionEntity {
167201 name : CString ,
168202 handler : Rc < dyn Callable > ,
169203 arguments : Vec < Argument > ,
204+ return_type : Option < ReturnType > ,
170205}
171206
172207impl FunctionEntity {
@@ -176,6 +211,7 @@ impl FunctionEntity {
176211 name : ensure_end_with_zero ( name) ,
177212 handler,
178213 arguments : Default :: default ( ) ,
214+ return_type : None ,
179215 }
180216 }
181217
@@ -192,14 +228,22 @@ impl FunctionEntity {
192228 self . arguments . extend ( arguments) ;
193229 self
194230 }
231+
232+ /// Add return type info.
233+ #[ inline]
234+ pub fn return_type ( & mut self , return_type : ReturnType ) -> & mut Self {
235+ self . return_type = Some ( return_type) ;
236+ self
237+ }
195238}
196239
197240/// Builder for registering class method.
198241pub struct MethodEntity {
199- name : CString ,
200- handler : Option < Rc < dyn Callable > > ,
242+ pub ( crate ) name : CString ,
243+ pub ( crate ) handler : Option < Rc < dyn Callable > > ,
201244 arguments : Vec < Argument > ,
202245 visibility : RawVisibility ,
246+ return_type : Option < ReturnType > ,
203247}
204248
205249impl MethodEntity {
@@ -212,6 +256,7 @@ impl MethodEntity {
212256 handler,
213257 visibility : visibility as RawVisibility ,
214258 arguments : Default :: default ( ) ,
259+ return_type : None ,
215260 }
216261 }
217262
@@ -240,6 +285,13 @@ impl MethodEntity {
240285 self . arguments . extend ( arguments) ;
241286 self
242287 }
288+
289+ /// Add return type info.
290+ #[ inline]
291+ pub fn return_type ( & mut self , return_type : ReturnType ) -> & mut Self {
292+ self . return_type = Some ( return_type) ;
293+ self
294+ }
243295}
244296
245297/// Function or method argument info.
@@ -291,6 +343,42 @@ impl Argument {
291343 }
292344}
293345
346+ /// Function or method return type.
347+ pub struct ReturnType {
348+ type_info : TypeInfo ,
349+ ret_by_ref : bool ,
350+ allow_null : bool ,
351+ }
352+
353+ impl ReturnType {
354+ /// Indicate the return type is return by value.
355+ #[ inline]
356+ pub fn by_val ( type_info : TypeInfo ) -> Self {
357+ Self {
358+ type_info,
359+ ret_by_ref : false ,
360+ allow_null : false ,
361+ }
362+ }
363+
364+ /// Indicate the return type is return by reference.
365+ #[ inline]
366+ pub fn by_ref ( type_info : TypeInfo ) -> Self {
367+ Self {
368+ type_info,
369+ ret_by_ref : true ,
370+ allow_null : false ,
371+ }
372+ }
373+
374+ /// Indicate the return type can be null.
375+ #[ inline]
376+ pub fn allow_null ( mut self ) -> Self {
377+ self . allow_null = true ;
378+ self
379+ }
380+ }
381+
294382/// Wrapper of [`zend_function`].
295383#[ repr( transparent) ]
296384pub struct ZFunc {
@@ -447,12 +535,43 @@ unsafe extern "C" fn invoke(execute_data: *mut zend_execute_data, return_value:
447535 let num_args = execute_data. common_num_args ( ) ;
448536 let arg_info = execute_data. common_arg_info ( ) ;
449537
450- let last_arg_info = arg_info. offset ( ( num_args + 1 ) as isize ) ;
451- let translator = CallableTranslator {
452- arg_info : * last_arg_info,
538+ // should be mysterious code
539+ let mysterious_arg_info = arg_info. offset ( ( num_args + 1 ) as isize ) ;
540+ let mysterious_code = slice:: from_raw_parts (
541+ mysterious_arg_info as * const u8 ,
542+ INVOKE_MYSTERIOUS_CODE . len ( ) ,
543+ ) ;
544+
545+ let handler = if mysterious_code == INVOKE_MYSTERIOUS_CODE {
546+ // hiddden real handler
547+ let last_arg_info = arg_info. offset ( ( num_args + 2 ) as isize ) ;
548+ let translator = CallableTranslator {
549+ arg_info : * last_arg_info,
550+ } ;
551+ let handler = translator. callable ;
552+ handler. as_ref ( ) . expect ( "handler is null" )
553+ } else {
554+ let function_name = execute_data
555+ . func ( )
556+ . get_function_name ( )
557+ . and_then ( |name| name. to_c_str ( ) . ok ( ) )
558+ . map ( CString :: from) ;
559+
560+ function_name
561+ . and_then ( |function_name| {
562+ let class_name = execute_data
563+ . func ( )
564+ . get_class ( )
565+ . and_then ( |cls| cls. get_name ( ) . to_c_str ( ) . ok ( ) )
566+ . map ( CString :: from) ;
567+
568+ global_module ( )
569+ . handler_map
570+ . get ( & ( class_name, function_name) )
571+ } )
572+ . expect ( "invoke handler is not correct" )
573+ . as_ref ( )
453574 } ;
454- let handler = translator. callable ;
455- let handler = handler. as_ref ( ) . expect ( "handler is null" ) ;
456575
457576 // Check arguments count.
458577 let num_args = execute_data. num_args ( ) ;
0 commit comments