ext_php_rs/zend/
function.rs1use std::{fmt::Debug, os::raw::c_char, ptr};
4
5use crate::{
6 convert::IntoZvalDyn,
7 error::Result,
8 ffi::{
9 zend_call_known_function, zend_fetch_function_str, zend_function, zend_function_entry,
10 zend_hash_str_find_ptr_lc,
11 },
12 flags::FunctionType,
13 types::Zval,
14};
15
16use super::ClassEntry;
17
18pub type FunctionEntry = zend_function_entry;
20
21impl Debug for FunctionEntry {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 f.debug_struct("_zend_function_entry")
24 .field("fname", &self.fname)
25 .field("arg_info", &self.arg_info)
26 .field("num_args", &self.num_args)
27 .field("flags", &self.flags)
28 .finish()
29 }
30}
31
32impl FunctionEntry {
33 pub fn end() -> Self {
35 Self {
36 fname: ptr::null() as *const c_char,
37 handler: None,
38 arg_info: ptr::null(),
39 num_args: 0,
40 flags: 0,
41 #[cfg(php84)]
42 doc_comment: ptr::null(),
43 #[cfg(php84)]
44 frameless_function_infos: ptr::null(),
45 }
46 }
47
48 pub fn into_raw(self) -> *mut Self {
51 Box::into_raw(Box::new(self))
52 }
53}
54
55pub type Function = zend_function;
56
57impl Function {
58 pub fn function_type(&self) -> FunctionType {
59 FunctionType::from(unsafe { self.type_ })
60 }
61
62 pub fn try_from_function(name: &str) -> Option<Self> {
63 unsafe {
64 let res = zend_fetch_function_str(name.as_ptr() as *const c_char, name.len());
65 if res.is_null() {
66 return None;
67 }
68 Some(*res)
69 }
70 }
71 pub fn try_from_method(class: &str, name: &str) -> Option<Self> {
72 match ClassEntry::try_find(class) {
73 None => None,
74 Some(ce) => unsafe {
75 let res = zend_hash_str_find_ptr_lc(
76 &ce.function_table,
77 name.as_ptr() as *const c_char,
78 name.len(),
79 ) as *mut zend_function;
80 if res.is_null() {
81 return None;
82 }
83 Some(*res)
84 },
85 }
86 }
87
88 #[inline(always)]
113 pub fn try_call(&self, params: Vec<&dyn IntoZvalDyn>) -> Result<Zval> {
114 let mut retval = Zval::new();
115 let len = params.len();
116 let params = params
117 .into_iter()
118 .map(|val| val.as_zval(false))
119 .collect::<Result<Vec<_>>>()?;
120 let packed = params.into_boxed_slice();
121
122 unsafe {
123 zend_call_known_function(
124 self as *const _ as *mut _,
125 std::ptr::null_mut(),
126 std::ptr::null_mut(),
127 &mut retval,
128 len as _,
129 packed.as_ptr() as *mut _,
130 std::ptr::null_mut(),
131 )
132 };
133
134 Ok(retval)
135 }
136}