Skip to content

Commit 374d0da

Browse files
committed
Add generic for Class and Object.
1 parent e09e78d commit 374d0da

File tree

26 files changed

+241
-185
lines changed

26 files changed

+241
-185
lines changed

examples/hello/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use phper::{
22
alloc::EBox,
33
arrays::Array,
4-
classes::StdClass,
4+
classes::DynamicClass,
55
functions::Argument,
66
ini::Policy,
77
modules::{Module, ModuleArgs},
@@ -63,19 +63,19 @@ pub fn get_module() -> Module {
6363
);
6464

6565
// register classes
66-
let mut foo_class = StdClass::new();
66+
let mut foo_class = DynamicClass::new();
6767
foo_class.add_property("foo", "100".to_string());
6868
foo_class.add_method(
6969
"getFoo",
70-
|this: &mut Object, _: &mut [Val]| -> phper::Result<Val> {
70+
|this: &mut Object<()>, _: &mut [Val]| -> phper::Result<Val> {
7171
let prop = this.get_property("foo");
7272
Ok(Val::new(prop.as_string_value()?))
7373
},
7474
vec![],
7575
);
7676
foo_class.add_method(
7777
"setFoo",
78-
|this: &mut Object, arguments: &mut [Val]| -> phper::Result<()> {
78+
|this: &mut Object<()>, arguments: &mut [Val]| -> phper::Result<()> {
7979
this.set_property("foo", Val::new(arguments[0].as_string_value()?));
8080
Ok(())
8181
},

examples/hello/tests/php/test.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@
66

77
assert_eq(hello_say_hello("world"), "Hello, world!\n");
88

9-
assert_eq(class_exists("Phper\\OtherException"), true);
10-
119
try {
1210
hello_throw_exception();
13-
} catch (Phper\OtherException $e) {
11+
} catch (ErrorException $e) {
1412
assert_eq($e->getMessage(), "I am sorry");
1513
}
1614

examples/http-client/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "mini-curl"
2+
name = "http-client"
33
version = "0.0.0"
44
authors = ["jmjoy <[email protected]>"]
55
edition = "2018"

examples/http-client/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use phper::{classes::StdClass, modules::Module, php_get_module};
1+
use phper::{classes::DynamicClass, modules::Module, php_get_module};
22

33
pub mod http_client;
44

@@ -11,7 +11,7 @@ pub fn get_module() -> Module {
1111
);
1212

1313
// let client = HttpClient::new();
14-
let client_class = StdClass::new();
14+
let client_class: DynamicClass<()> = DynamicClass::new();
1515
module.add_class("HttpClient", client_class);
1616

1717
module

examples/logging/tests/integration.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn test_php() {
88
.join("php");
99

1010
test_php_scripts_with_condition(
11-
env!("CARGO_BIN_EXE_log"),
11+
env!("CARGO_BIN_EXE_logging"),
1212
&[
1313
(&base_dir.join("test_php_say.php"), &|output| {
1414
let stdout = str::from_utf8(&output.stdout).unwrap();

phper-build/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Add this crate in your `[build-dependencies]` and using in `build.rs`.
1010
[Unlicense](https://github.com/jmjoy/phper/blob/master/LICENSE).
1111
*/
1212

13-
use phper_sys::{PHP_DEBUG, PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION, USING_ZTS};
13+
use phper_sys::*;
1414

1515
/// Register useful rust cfg for project using phper.
1616
pub fn register_configures() {

phper-sys/php_wrapper.c

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,12 @@ void phper_zend_string_release(zend_string *s) {
7474
return zend_string_release(s);
7575
}
7676

77-
void phper_zend_hash_str_update(HashTable *ht, const char *key, size_t len, zval *pData) {
78-
zend_hash_str_update(ht, key, len, pData);
77+
zval *phper_zend_hash_str_update(HashTable *ht, const char *key, size_t len, zval *pData) {
78+
return zend_hash_str_update(ht, key, len, pData);
79+
}
80+
81+
zval* phper_zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData) {
82+
return zend_hash_index_update(ht, h, pData);
7983
}
8084

8185
void phper_array_init(zval *arg) {
@@ -86,10 +90,6 @@ void *phper_zend_hash_str_find_ptr(const HashTable *ht, const char *str, size_t
8690
return zend_hash_str_find_ptr(ht, str, len);
8791
}
8892

89-
zval* phper_zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData) {
90-
return zend_hash_index_update(ht, h, pData);
91-
}
92-
9393
void phper_zend_hash_merge_with_key(HashTable *target, HashTable *source) {
9494
uint32_t idx;
9595
Bucket *p;
@@ -116,6 +116,32 @@ void phper_zval_obj(zval *z, zend_object *o) {
116116
ZVAL_OBJ(z, o);
117117
}
118118

119-
int phper_z_type_info_refcounted(uint32_t t) {
120-
return Z_TYPE_INFO_REFCOUNTED(t);
121-
}
119+
static zend_string *phper_zend_string_concat3(
120+
const char *str1, size_t str1_len,
121+
const char *str2, size_t str2_len,
122+
const char *str3, size_t str3_len)
123+
{
124+
size_t len = str1_len + str2_len + str3_len;
125+
zend_string *res = zend_string_alloc(len, 0);
126+
127+
memcpy(ZSTR_VAL(res), str1, str1_len);
128+
memcpy(ZSTR_VAL(res) + str1_len, str2, str2_len);
129+
memcpy(ZSTR_VAL(res) + str1_len + str2_len, str3, str3_len);
130+
ZSTR_VAL(res)[len] = '\0';
131+
132+
return res;
133+
}
134+
135+
zend_string *phper_get_function_or_method_name(const zend_function *func) {
136+
#if PHP_VERSION_ID >= 80000
137+
return get_function_or_method_name(func);
138+
#else
139+
if (func->common.scope) {
140+
return phper_zend_string_concat3(
141+
ZSTR_VAL(func->common.scope->name), ZSTR_LEN(func->common.scope->name),
142+
"::", sizeof("::") - 1,
143+
ZSTR_VAL(func->common.function_name), ZSTR_LEN(func->common.function_name));
144+
}
145+
return func->common.function_name ? zend_string_copy(func->common.function_name) : zend_string_init("main", sizeof("main") - 1, 0);
146+
#endif
147+
}

phper-sys/php_wrapper.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ zend_string *phper_zend_string_init(const char *str, size_t len, int persistent)
3232
zend_string *phper_zend_string_alloc(size_t len, int persistent);
3333
void phper_zend_string_release(zend_string *s);
3434

35-
void phper_zend_hash_str_update(HashTable *ht, const char *key, size_t len, zval *pData);
35+
zval *phper_zend_hash_str_update(HashTable *ht, const char *key, size_t len, zval *pData);
36+
zval* phper_zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData);
3637

3738
void phper_array_init(zval *arg);
3839
void *phper_zend_hash_str_find_ptr(const HashTable *ht, const char *str, size_t len);
39-
zval* phper_zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData);
4040
void phper_zend_hash_merge_with_key(HashTable *target, HashTable *source);
4141

4242
void phper_zval_obj(zval *z, zend_object *o);
4343

44-
int phper_z_type_info_refcounted(uint32_t t);
44+
zend_string *phper_get_function_or_method_name(const zend_function *func);
4545

4646
#endif //PHPER_PHP_WRAPPER_H

phper/src/arrays.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl Array {
6161
unsafe {
6262
match key {
6363
Key::Index(i) => {
64-
zend_hash_index_update(&mut self.inner, i, EBox::into_raw(value).cast());
64+
phper_zend_hash_index_update(&mut self.inner, i, EBox::into_raw(value).cast());
6565
}
6666
Key::Str(s) => {
6767
phper_zend_hash_str_update(

phper/src/classes.rs

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,51 @@
33
use crate::{
44
errors::ClassNotFoundError,
55
functions::{Argument, Callable, FunctionEntity, FunctionEntry, Method},
6+
objects::Object,
67
sys::*,
78
utils::ensure_end_with_zero,
9+
values::{SetVal, Val},
810
};
911
use once_cell::sync::OnceCell;
1012
use std::{
13+
marker::PhantomData,
1114
mem::zeroed,
1215
os::raw::c_int,
1316
ptr::null_mut,
1417
sync::atomic::{AtomicPtr, Ordering},
1518
};
1619

17-
pub trait Class: Send + Sync {
20+
pub trait Classifiable {
1821
fn methods(&mut self) -> &mut [FunctionEntity];
1922
fn properties(&mut self) -> &mut [PropertyEntity];
2023
fn parent(&self) -> Option<&str>;
2124
}
2225

23-
pub struct StdClass {
26+
pub struct DynamicClass<T: Send + Sync + 'static> {
2427
pub(crate) method_entities: Vec<FunctionEntity>,
2528
pub(crate) property_entities: Vec<PropertyEntity>,
2629
pub(crate) parent: Option<String>,
30+
_p: PhantomData<T>,
2731
}
2832

29-
impl StdClass {
33+
impl<T: Send + Sync + 'static> DynamicClass<T> {
3034
pub fn new() -> Self {
3135
Self {
3236
method_entities: Vec::new(),
3337
property_entities: Vec::new(),
3438
parent: None,
39+
_p: Default::default(),
3540
}
3641
}
3742

38-
pub fn add_method(
39-
&mut self,
40-
name: impl ToString,
41-
handler: impl Method + 'static,
42-
arguments: Vec<Argument>,
43-
) {
43+
pub fn add_method<F, R>(&mut self, name: impl ToString, handler: F, arguments: Vec<Argument>)
44+
where
45+
F: Fn(&mut Object<T>, &mut [Val]) -> R + Send + Sync + 'static,
46+
R: SetVal + 'static,
47+
{
4448
self.method_entities.push(FunctionEntity::new(
4549
name,
46-
Callable::Method(Box::new(handler), AtomicPtr::new(null_mut())),
50+
Box::new(Method::new(handler)),
4751
arguments,
4852
));
4953
}
@@ -59,7 +63,7 @@ impl StdClass {
5963
}
6064
}
6165

62-
impl Class for StdClass {
66+
impl<T: Send + Sync> Classifiable for DynamicClass<T> {
6367
fn methods(&mut self) -> &mut [FunctionEntity] {
6468
&mut self.method_entities
6569
}
@@ -117,12 +121,12 @@ fn find_global_class_entry_ptr(name: impl AsRef<str>) -> *mut zend_class_entry {
117121
pub struct ClassEntity {
118122
pub(crate) name: String,
119123
pub(crate) entry: AtomicPtr<ClassEntry>,
120-
pub(crate) class: Box<dyn Class>,
124+
pub(crate) class: Box<dyn Classifiable>,
121125
pub(crate) function_entries: OnceCell<AtomicPtr<FunctionEntry>>,
122126
}
123127

124128
impl ClassEntity {
125-
pub(crate) unsafe fn new(name: impl ToString, class: impl Class + 'static) -> Self {
129+
pub(crate) unsafe fn new(name: impl ToString, class: impl Classifiable + 'static) -> Self {
126130
Self {
127131
name: name.to_string(),
128132
entry: AtomicPtr::new(null_mut()),
@@ -138,26 +142,28 @@ impl ClassEntity {
138142
self.function_entries().load(Ordering::SeqCst).cast(),
139143
);
140144

141-
let parent = self.class.parent().map(|s| match s {
142-
"Exception" | "\\Exception" => zend_ce_exception,
143-
_ => todo!(),
144-
});
145+
let parent = self
146+
.class
147+
.parent()
148+
.map(|s| ClassEntry::from_globals(s).unwrap());
145149

146150
let ptr = match parent {
147-
Some(parent) => zend_register_internal_class_ex(&mut class_ce, parent).cast(),
151+
Some(parent) => {
152+
zend_register_internal_class_ex(&mut class_ce, parent.as_ptr() as *mut _).cast()
153+
}
148154
None => zend_register_internal_class(&mut class_ce).cast(),
149155
};
150156
self.entry.store(ptr, Ordering::SeqCst);
151157

152-
let methods = self.class.methods();
153-
for method in methods {
154-
match &method.handler {
155-
Callable::Method(_, class) => {
156-
class.store(ptr, Ordering::SeqCst);
157-
}
158-
_ => unreachable!(),
159-
}
160-
}
158+
// let methods = self.class.methods();
159+
// for method in methods {
160+
// match &method.handler {
161+
// Callable::Method(_, class) => {
162+
// class.store(ptr, Ordering::SeqCst);
163+
// }
164+
// _ => unreachable!(),
165+
// }
166+
// }
161167
}
162168

163169
pub(crate) unsafe fn declare_properties(&mut self) {

0 commit comments

Comments
 (0)