Skip to content

Commit 07fca95

Browse files
committed
Fail to wrap zend_parse_parameters.
1 parent ac15b5e commit 07fca95

File tree

9 files changed

+150
-20
lines changed

9 files changed

+150
-20
lines changed

examples/simple/src/lib.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use phper::sys::{ZEND_RESULT_CODE_SUCCESS, zend_parse_parameters, zend_internal_
33
use phper::sys::{zend_ini_entry_def, zend_module_entry, zend_register_ini_entries, zend_unregister_ini_entries, OnUpdateBool, phper_zval_string};
44
use phper::sys::{OnUpdateString, zend_class_entry, zend_register_internal_class, zend_declare_property_string, ZEND_ACC_PUBLIC, zend_type, zend_read_property};
55
use phper::zend::api::{FunctionEntries, ModuleGlobals, function_entry_end};
6-
use phper::zend::compile::{InternalArgInfos, internal_arg_info_begin};
6+
use phper::zend::compile::{MultiInternalArgInfo, internal_arg_info_begin};
77
use phper::zend::ini::{IniEntryDefs, ini_entry_def_end};
88
use phper::zend::modules::{ModuleEntry, create_zend_module_entry, ModuleArgs};
99
use phper::zend::types::{ExecuteData, Val, SetVal, Value, ClassEntry};
@@ -56,9 +56,11 @@ fn r_shutdown_simple(args: ModuleArgs) -> bool {
5656
}
5757

5858
#[php_minfo_function]
59-
fn m_info_simple(zend_module: *mut ::phper::sys::zend_module_entry) {
59+
fn m_info_simple(module: &ModuleEntry) {
6060
unsafe {
6161
php_info_print_table_start();
62+
php_info_print_table_row(2, c_str_ptr!("simple.version"), (*module.as_ptr()).version);
63+
php_info_print_table_row(2, c_str_ptr!("simple.build_id"), (*module.as_ptr()).build_id);
6264
php_info_print_table_row(2, c_str_ptr!("simple.enable"), if SIMPLE_ENABLE.get() { c_str_ptr!("1") } else { c_str_ptr!("0") });
6365
php_info_print_table_row(2, c_str_ptr!("simple.text"), SIMPLE_TEXT.get());
6466
php_info_print_table_end();
@@ -85,18 +87,22 @@ pub fn test_simple(execute_data: ExecuteData) -> impl SetVal {
8587
return None;
8688
}
8789

88-
let s = CStr::from_ptr((*SIMPLE_TEXT.as_ptr())).to_str().unwrap();
89-
println!("simple.text: '{}'", s);
90-
9190
Some(format!(
92-
"(a . b) = {}{}",
91+
"a = {}, a_len = {}, b = {}, b_len = {}",
9392
CStr::from_ptr(a).to_str().unwrap(),
93+
a_len,
9494
CStr::from_ptr(b).to_str().unwrap(),
95+
b_len,
9596
))
9697
}
9798
}
9899

99-
static ARG_INFO_TEST_SIMPLE: InternalArgInfos<3> = InternalArgInfos::new([
100+
#[php_function]
101+
pub fn test_parse(execute_data: ExecuteData) -> impl SetVal {
102+
execute_data.parse_parameters::<bool>()
103+
}
104+
105+
static ARG_INFO_TEST_SIMPLE: MultiInternalArgInfo<3> = MultiInternalArgInfo::new([
100106
internal_arg_info_begin(2, false),
101107
zend_internal_arg_info {
102108
name: c_str_ptr!("a"),
@@ -112,21 +118,28 @@ static ARG_INFO_TEST_SIMPLE: InternalArgInfos<3> = InternalArgInfos::new([
112118
},
113119
]);
114120

115-
static FUNCTION_ENTRIES: FunctionEntries<2> = FunctionEntries::new([
121+
static FUNCTION_ENTRIES: FunctionEntries<3> = FunctionEntries::new([
116122
zend_function_entry {
117123
fname: c_str_ptr!("test_simple"),
118124
handler: Some(php_fn!(test_simple)),
119125
arg_info: ARG_INFO_TEST_SIMPLE.get(),
120126
num_args: 2,
121127
flags: 0,
122128
},
129+
zend_function_entry {
130+
fname: c_str_ptr!("test_parse"),
131+
handler: Some(php_fn!(test_parse)),
132+
arg_info: null(),
133+
num_args: 0,
134+
flags: 0,
135+
},
123136
function_entry_end(),
124137
]);
125138

126139

127-
static ARG_INFO_MY_CLASS_FOO: InternalArgInfos<2> = InternalArgInfos::new([
140+
static ARG_INFO_MY_CLASS_FOO: MultiInternalArgInfo<2> = MultiInternalArgInfo::new([
128141
zend_internal_arg_info {
129-
name: 2 as *const _,
142+
name: 1 as *const _,
130143
type_: 0,
131144
pass_by_reference: 0,
132145
is_variadic: 0,

examples/simple/tests/confirm_compiled.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
var_dump(get_extension_funcs('simple'));
88
var_dump(test_simple("aaa", "bbb"));
99
var_dump((new MyClass())->foo("foo-"));
10+
11+
var_dump(test_parse(false));

phper-macros/src/inner.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub(crate) fn hook_fn(input: TokenStream, prefix: impl ToString) -> TokenStream
4242

4343
result.into()
4444
}
45+
4546
pub(crate) fn info_fn(input: TokenStream, prefix: impl ToString) -> TokenStream {
4647
let input = parse_macro_input!(input as ItemFn);
4748

@@ -62,8 +63,8 @@ pub(crate) fn info_fn(input: TokenStream, prefix: impl ToString) -> TokenStream
6263
#body
6364
}
6465

65-
let internal: fn(*mut ::phper::sys::zend_module_entry) = internal;
66-
internal(zend_module)
66+
let internal: fn(&::phper::zend::modules::ModuleEntry) = internal;
67+
internal(::phper::zend::modules::ModuleEntry::from_ptr(zend_module))
6768
}
6869
};
6970

phper-sys/php_wrapper.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ zend_uchar phper_zval_get_type(const zval* pz) {
2424

2525
void phper_zval_stringl(zval *return_value, const char *s, size_t len) {
2626
ZVAL_STRINGL(return_value, s, len);
27-
}
27+
}

phper/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Version `0.1.x` will be a preview version.
3030

3131
pub mod zend;
3232
mod error;
33+
mod utils;
3334

3435
pub use phper_alloc as alloc;
3536
pub use phper_sys as sys;

phper/src/utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use std::intrinsics::transmute;

phper/src/zend/compile.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ pub const fn internal_arg_info_begin(required_num_args: usize, return_reference:
1010
}
1111
}
1212

13-
pub struct InternalArgInfos<const N: usize> {
13+
pub struct MultiInternalArgInfo<const N: usize> {
1414
inner: UnsafeCell<[zend_internal_arg_info; N]>,
1515
}
1616

17-
impl<const N: usize> InternalArgInfos<N> {
17+
impl<const N: usize> MultiInternalArgInfo<N> {
1818
pub const fn new(inner: [zend_internal_arg_info; N]) -> Self {
1919
Self { inner: UnsafeCell::new(inner) }
2020
}
@@ -24,4 +24,4 @@ impl<const N: usize> InternalArgInfos<N> {
2424
}
2525
}
2626

27-
unsafe impl<const N: usize> Sync for InternalArgInfos<N> {}
27+
unsafe impl<const N: usize> Sync for MultiInternalArgInfo<N> {}

phper/src/zend/modules.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub const fn create_zend_module_entry(
5555
}
5656
}
5757

58+
#[repr(transparent)]
5859
pub struct ModuleEntry {
5960
raw: Cell<zend_module_entry>,
6061
}
@@ -67,6 +68,10 @@ impl ModuleEntry {
6768
pub const fn as_ptr(&self) -> *mut zend_module_entry {
6869
self.raw.as_ptr()
6970
}
71+
72+
pub fn from_ptr<'a>(ptr: *const zend_module_entry) -> &'a Self {
73+
unsafe { &*(ptr as *const Self) }
74+
}
7075
}
7176

7277
unsafe impl Sync for ModuleEntry {}

phper/src/zend/types.rs

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ use crate::sys::{zend_execute_data, zval, zend_type, phper_zval_get_type, IS_STR
22
IS_TRUE, IS_FALSE, phper_zval_stringl, zend_throw_exception,
33
zend_class_entry, phper_init_class_entry, zend_register_internal_class,
44
zend_declare_property_stringl, zend_declare_property, IS_LONG,
5+
zend_parse_parameters, ZEND_RESULT_CODE_SUCCESS,
56
};
67
use crate::c_str_ptr;
7-
use std::ffi::CStr;
8-
use std::borrow::Cow;
8+
use std::ffi::{CStr, c_void};
9+
use std::borrow::{Cow, Borrow};
910
use crate::zend::exceptions::Throwable;
1011
use std::ptr::{null, null_mut};
1112
use std::cell::Cell;
@@ -83,11 +84,117 @@ impl ExecuteData {
8384
}
8485
}
8586

86-
pub fn parse_parameters(&self) {
87+
pub fn parse_parameters<T: ParseParameter>(&self) -> Option<T> {
88+
<T>::parse(self.num_args())
89+
}
90+
}
91+
92+
pub trait ParseParameter: Sized {
93+
fn parse(arg_num: usize) -> Option<Self>;
94+
}
8795

96+
impl ParseParameter for bool {
97+
fn parse(num_args: usize) -> Option<Self> {
98+
let mut b = false;
99+
if unsafe { zend_parse_parameters(num_args as c_int, c_str_ptr!("b"), &mut b) == ZEND_RESULT_CODE_SUCCESS } {
100+
Some(b)
101+
} else {
102+
None
103+
}
104+
// if (c_str_ptr!("b"), &mut b as *const _).call_zend_parse_parameters(arg_num) {
105+
// if zend_parse_fixed_parameters(num_args, "b\0", parameters) {
106+
// } else {
107+
// None
108+
// }
88109
}
89110
}
90111

112+
// impl<A: ParseParameter, B: ParseParameter> ParseParameter for (A, B) {
113+
// fn spec() -> Cow<'static, str> {
114+
// let mut s= String::new();
115+
// s.push_str(&<A>::spec());
116+
// s.push_str(&<B>::spec());
117+
// Cow::Owned(s)
118+
// }
119+
//
120+
// fn push_parameters(parameters: &mut Vec<*const c_void>) {
121+
// unimplemented!()
122+
// }
123+
//
124+
// fn parse(arg_num: i32) -> Option<Self> {
125+
// let a = null_mut();
126+
// let b = null_mut();
127+
//
128+
// #[repr(C)]
129+
// struct Parameters(*mut c_void, *mut c_void);
130+
//
131+
// let parameters = Parameters(a, b);
132+
//
133+
// let result = unsafe {
134+
// zend_parse_parameters(arg_num, (&*Self::spec()).as_ptr().cast(), parameters) == ZEND_RESULT_CODE_SUCCESS
135+
// };
136+
// }
137+
// }
138+
139+
fn zend_parse_fixed_parameters(num_args: usize, type_spec: &str, parameters: [*mut c_void; 10]) -> bool {
140+
assert!(num_args <= 10);
141+
assert!(type_spec.ends_with('\0'));
142+
143+
let mut fixed_parameters = [null_mut(); 20];
144+
145+
let mut i = 0;
146+
for c in type_spec.chars() {
147+
match c {
148+
's' => {
149+
fixed_parameters[i] = parameters[i];
150+
i += 1;
151+
}
152+
'*' | '+' | '|' | '/' | '!' | '\0' => {}
153+
_ => {
154+
fixed_parameters[i] = parameters[i];
155+
}
156+
}
157+
i += 1;
158+
}
159+
160+
unsafe {
161+
zend_parse_parameters(num_args as c_int, type_spec.as_ptr().cast(), fixed_parameters) == ZEND_RESULT_CODE_SUCCESS
162+
}
163+
}
164+
165+
trait CallZendParseParameters {
166+
fn call_zend_parse_parameters(self, num_args: c_int) -> bool;
167+
}
168+
169+
macro_rules! generate_impl_call_zend_parse_parameters {
170+
{ $(($n:tt, $T:ident)),*} => {
171+
impl<$($T,)*> CallZendParseParameters for (*const c_char, $(*const $T,)*) {
172+
#[inline]
173+
fn call_zend_parse_parameters(self, num_args: i32) -> bool {
174+
unsafe {
175+
zend_parse_parameters(num_args, self.0, $(self.$n,)*) == ZEND_RESULT_CODE_SUCCESS
176+
}
177+
}
178+
}
179+
};
180+
}
181+
182+
generate_impl_call_zend_parse_parameters!();
183+
generate_impl_call_zend_parse_parameters!((1, A));
184+
generate_impl_call_zend_parse_parameters!((1, A), (2, B));
185+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C));
186+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D));
187+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D), (5, E));
188+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D), (5, E), (6, F));
189+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D), (5, E), (6, F), (7, G));
190+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D), (5, E), (6, F), (7, G), (8, H));
191+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D), (5, E), (6, F), (7, G), (8, H), (9, I));
192+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D), (5, E), (6, F), (7, G), (8, H), (9, I), (10, J));
193+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D), (5, E), (6, F), (7, G), (8, H), (9, I), (10, J), (11, K));
194+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D), (5, E), (6, F), (7, G), (8, H), (9, I), (10, J), (11, K), (12, L));
195+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D), (5, E), (6, F), (7, G), (8, H), (9, I), (10, J), (11, K), (12, L), (13, M));
196+
generate_impl_call_zend_parse_parameters!((1, A), (2, B), (3, C), (4, D), (5, E), (6, F), (7, G), (8, H), (9, I), (10, J), (11, K), (12, L), (13, M), (14, N));
197+
91198
#[repr(u32)]
92199
pub enum ValType {
93200
UNDEF = crate::sys::IS_UNDEF,
@@ -234,4 +341,4 @@ impl SetVal for Value<'_> {
234341
Value::String(s) => s.set_val(val),
235342
}
236343
}
237-
}
344+
}

0 commit comments

Comments
 (0)