Skip to content

Commit f761a2e

Browse files
committed
Rewrite implement SetVal for Array.
1 parent cfcbebd commit f761a2e

File tree

11 files changed

+163
-40
lines changed

11 files changed

+163
-40
lines changed

examples/hello/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ pub fn get_module() -> Module {
5151
let mut arr = Array::new();
5252

5353
let mut hello_enable = Val::new(Module::get_bool_ini("hello.enable"));
54-
arr.insert("hello.enable", &mut hello_enable);
54+
arr.insert("hello.enable", hello_enable);
5555

5656
let mut hello_description = Val::new(Module::get_str_ini("hello.description"));
57-
arr.insert("hello.description", &mut hello_description);
57+
arr.insert("hello.description", hello_description);
5858

5959
arr
6060
},

phper-sys/php_wrapper.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,26 @@ void phper_zend_hash_str_update(HashTable *ht, const char *key, size_t len, zval
8080

8181
void phper_array_init(zval *arg) {
8282
array_init(arg);
83-
}
83+
}
84+
85+
void phper_zend_hash_merge_with_key(HashTable *target, HashTable *source) {
86+
uint32_t idx;
87+
Bucket *p;
88+
zval *s;
89+
90+
for (idx = 0; idx < source->nNumUsed; idx++) {
91+
p = source->arData + idx;
92+
s = &p->val;
93+
if (UNEXPECTED(Z_TYPE_P(s) == IS_INDIRECT)) {
94+
s = Z_INDIRECT_P(s);
95+
}
96+
if (UNEXPECTED(Z_TYPE_P(s) == IS_UNDEF)) {
97+
continue;
98+
}
99+
if (p->key) {
100+
zend_hash_str_update(target, ZSTR_VAL(p->key), ZSTR_LEN(p->key), s);
101+
} else {
102+
zend_hash_index_update(target, p->h, s);
103+
}
104+
}
105+
}

phper-sys/php_wrapper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ void phper_zend_string_release(zend_string *s);
3535
void phper_zend_hash_str_update(HashTable *ht, const char *key, size_t len, zval *pData);
3636

3737
void phper_array_init(zval *arg);
38-
38+
void phper_zend_hash_merge_with_key(HashTable *target, HashTable *source);
3939

4040
#endif //PHPER_PHP_WRAPPER_H

phper/src/arrays.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{sys::*, values::Val};
2-
use std::mem::{size_of, zeroed};
2+
use std::mem::zeroed;
33

44
#[repr(transparent)]
55
pub struct Array {
@@ -15,6 +15,11 @@ impl Array {
1515
}
1616
}
1717

18+
pub(crate) unsafe fn from_raw<'a>(ptr: *mut zend_array) -> &'a mut Array {
19+
let ptr = ptr as *mut Array;
20+
ptr.as_mut().expect("ptr shouldn't be null")
21+
}
22+
1823
pub fn as_ptr(&self) -> *const zend_array {
1924
&self.inner
2025
}
@@ -23,7 +28,7 @@ impl Array {
2328
&mut self.inner
2429
}
2530

26-
pub fn insert(&mut self, key: impl AsRef<str>, value: &mut Val) {
31+
pub fn insert(&mut self, key: impl AsRef<str>, mut value: Val) {
2732
let key = key.as_ref();
2833
unsafe {
2934
phper_zend_hash_str_update(

phper/src/classes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use once_cell::sync::OnceCell;
1010
use crate::{
1111
functions::{Argument, Callable, FunctionEntity, FunctionEntry, Method},
1212
sys::*,
13-
values::{SetVal, Val},
13+
values::SetVal,
1414
};
1515

1616
pub trait Class: Send + Sync {

phper/src/functions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ where
2222
R: SetVal,
2323
{
2424
fn call(&self, arguments: &mut [Val], return_value: &mut Val) {
25-
let mut r = self(arguments);
25+
let r = self(arguments);
2626
r.set_val(return_value);
2727
}
2828
}

phper/src/modules.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,14 @@ use crate::{
77
utils::ensure_end_with_zero,
88
EXCEPTION_CLASS_NAME,
99
};
10-
use once_cell::sync::Lazy;
1110
use std::{
1211
borrow::BorrowMut,
1312
cell::RefCell,
1413
collections::HashMap,
1514
mem::{size_of, zeroed},
1615
os::raw::{c_int, c_uchar, c_uint, c_ushort},
1716
ptr::{null, null_mut},
18-
sync::{
19-
atomic::{AtomicPtr, Ordering},
20-
RwLock,
21-
},
17+
sync::atomic::{AtomicPtr, Ordering},
2218
};
2319

2420
static GLOBAL_MODULE: AtomicPtr<Module> = AtomicPtr::new(null_mut());

phper/src/types.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::sys::*;
22
use num_traits::cast::FromPrimitive;
3-
use std::{convert::TryInto, ffi::CStr, os::raw::c_int};
3+
use std::{ffi::CStr, os::raw::c_int};
44

55
#[derive(FromPrimitive, PartialEq)]
66
#[repr(u32)]
@@ -13,7 +13,9 @@ pub enum Type {
1313
Long = IS_LONG,
1414
Double = IS_DOUBLE,
1515
String = IS_STRING,
16+
StringEx = IS_STRING_EX,
1617
Array = IS_ARRAY,
18+
ArrayEx = IS_ARRAY_EX,
1719
Object = IS_OBJECT,
1820
Resource = IS_RESOURCE,
1921
Reference = IS_REFERENCE,

phper/src/values.rs

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
use crate::{
22
arrays::Array,
33
errors::Throwable,
4+
objects::Object,
45
sys::*,
56
types::{get_type_by_const, Type},
67
utils::ensure_end_with_zero,
78
TypeError,
89
};
910
use std::{
10-
mem::zeroed,
11-
os::raw::{c_char, c_int},
12-
slice::from_raw_parts,
13-
str,
14-
str::Utf8Error,
11+
mem::zeroed, os::raw::c_char, slice::from_raw_parts, str, str::Utf8Error,
1512
sync::atomic::Ordering,
1613
};
1714

@@ -118,24 +115,21 @@ impl Val {
118115
&mut self.inner
119116
}
120117

121-
pub fn set(&mut self, mut v: impl SetVal) {
118+
pub fn set(&mut self, v: impl SetVal) {
122119
v.set_val(self);
123120
}
124121

125-
#[inline]
126122
fn get_type(&self) -> Type {
127123
let t = unsafe { self.inner.u1.type_info };
128124
t.into()
129125
}
130126

131127
fn get_type_name(&self) -> crate::Result<String> {
132-
get_type_by_const(unsafe { self.get_type() as u32 })
128+
get_type_by_const(self.get_type() as u32)
133129
}
134130

135131
fn set_type(&mut self, t: Type) {
136-
unsafe {
137-
self.inner.u1.type_info = t as u32;
138-
}
132+
self.inner.u1.type_info = t as u32;
139133
}
140134

141135
pub fn as_bool(&self) -> crate::Result<bool> {
@@ -167,15 +161,14 @@ impl Val {
167161
}
168162

169163
pub fn as_string(&self) -> crate::Result<String> {
170-
if self.get_type() == Type::String {
171-
unsafe {
164+
match self.get_type() {
165+
Type::String | Type::StringEx => unsafe {
172166
let s = self.inner.value.str;
173167
let buf = from_raw_parts(&(*s).val as *const c_char as *const u8, (*s).len);
174168
let string = str::from_utf8(buf)?.to_string();
175169
Ok(string)
176-
}
177-
} else {
178-
Err(self.must_be_type_error("string").into())
170+
},
171+
_ => Err(self.must_be_type_error("string").into()),
179172
}
180173
}
181174

@@ -189,7 +182,29 @@ impl Val {
189182
}
190183
}
191184

192-
pub fn as_array(&self) {}
185+
pub fn as_array(&self) -> crate::Result<&Array> {
186+
match self.get_type() {
187+
Type::Array | Type::ArrayEx => unsafe {
188+
let ptr = self.inner.value.arr;
189+
Ok(Array::from_raw(ptr))
190+
},
191+
_ => Err(self.must_be_type_error("array").into()),
192+
}
193+
}
194+
195+
pub fn as_mut_array(&mut self) -> crate::Result<&mut Array> {
196+
match self.get_type() {
197+
Type::Array | Type::ArrayEx => unsafe {
198+
let ptr = self.inner.value.arr;
199+
Ok(Array::from_raw(ptr))
200+
},
201+
_ => Err(self.must_be_type_error("array").into()),
202+
}
203+
}
204+
205+
pub fn as_object(&self) -> crate::Result<Object> {
206+
todo!()
207+
}
193208

194209
fn must_be_type_error(&self, expect_type: &str) -> crate::Error {
195210
match self.get_type_name() {
@@ -200,6 +215,16 @@ impl Val {
200215
Err(e) => e.into(),
201216
}
202217
}
218+
219+
fn deep_copy(&self, other: &mut Val) -> crate::Result<()> {
220+
match self.get_type() {
221+
Type::Null => SetVal::set_val((), other),
222+
Type::Long => SetVal::set_val(self.as_i64()?, other),
223+
Type::String | Type::StringEx => SetVal::set_val(self.as_string()?, other),
224+
_ => unreachable!(),
225+
}
226+
Ok(())
227+
}
203228
}
204229

205230
pub trait SetVal {
@@ -267,18 +292,18 @@ impl SetVal for String {
267292
impl SetVal for Array {
268293
fn set_val(mut self, val: &mut Val) {
269294
unsafe {
270-
let mut new_val = Val::empty();
271-
phper_zval_arr(new_val.as_mut_ptr(), self.as_mut_ptr());
272-
phper_zval_zval(
273-
val.as_mut_ptr(),
274-
new_val.as_mut_ptr(),
275-
true.into(),
276-
false.into(),
277-
);
295+
phper_array_init(val.as_mut_ptr());
296+
phper_zend_hash_merge_with_key((*val.as_mut_ptr()).value.arr, self.as_mut_ptr());
278297
}
279298
}
280299
}
281300

301+
extern "C" fn array_copy_ctor(zv: *mut zval) {
302+
let val = unsafe { Val::from_mut(zv) };
303+
let other = unsafe { Val::from_mut(zv) };
304+
val.deep_copy(other).expect("deep copy failed");
305+
}
306+
282307
impl<T: SetVal> SetVal for Option<T> {
283308
fn set_val(self, val: &mut Val) {
284309
match self {

tests/integration/src/values.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use phper::{modules::Module, values::Val};
1+
use phper::{arrays::Array, modules::Module, values::Val};
22

33
pub fn integrate(module: &mut Module) {
44
integrate_returns(module);
@@ -10,24 +10,90 @@ fn integrate_returns(module: &mut Module) {
1010
integration_values_return_null,
1111
vec![],
1212
);
13+
module.add_function(
14+
"integration_values_return_true",
15+
integration_values_return_true,
16+
vec![],
17+
);
18+
module.add_function(
19+
"integration_values_return_false",
20+
integration_values_return_false,
21+
vec![],
22+
);
1323
module.add_function(
1424
"integration_values_return_i32",
1525
integration_values_return_i32,
1626
vec![],
1727
);
28+
module.add_function(
29+
"integration_values_return_u32",
30+
integration_values_return_u32,
31+
vec![],
32+
);
1833
module.add_function(
1934
"integration_values_return_i64",
2035
integration_values_return_i64,
2136
vec![],
2237
);
38+
module.add_function(
39+
"integration_values_return_f64",
40+
integration_values_return_f64,
41+
vec![],
42+
);
43+
module.add_function(
44+
"integration_values_return_str",
45+
integration_values_return_str,
46+
vec![],
47+
);
48+
module.add_function(
49+
"integration_values_return_string",
50+
integration_values_return_string,
51+
vec![],
52+
);
53+
module.add_function(
54+
"integration_values_return_array",
55+
integration_values_return_array,
56+
vec![],
57+
);
2358
}
2459

2560
fn integration_values_return_null(_: &mut [Val]) {}
2661

62+
fn integration_values_return_true(_: &mut [Val]) -> bool {
63+
true
64+
}
65+
66+
fn integration_values_return_false(_: &mut [Val]) -> bool {
67+
false
68+
}
69+
2770
fn integration_values_return_i32(_: &mut [Val]) -> i32 {
2871
32
2972
}
3073

74+
fn integration_values_return_u32(_: &mut [Val]) -> u32 {
75+
32
76+
}
77+
3178
fn integration_values_return_i64(_: &mut [Val]) -> i64 {
3279
64
3380
}
81+
82+
fn integration_values_return_f64(_: &mut [Val]) -> f64 {
83+
64.0
84+
}
85+
86+
fn integration_values_return_str(_: &mut [Val]) -> &'static str {
87+
"foo"
88+
}
89+
90+
fn integration_values_return_string(_: &mut [Val]) -> String {
91+
"foo".to_string()
92+
}
93+
94+
fn integration_values_return_array(_: &mut [Val]) -> Array {
95+
let mut arr = Array::new();
96+
arr.insert("a", Val::new(1));
97+
arr.insert("b", Val::new("foo"));
98+
arr
99+
}

0 commit comments

Comments
 (0)