Skip to content

Commit aee0a13

Browse files
committed
Add drop for Val.
1 parent 0b600a8 commit aee0a13

File tree

10 files changed

+61
-99
lines changed

10 files changed

+61
-99
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# PHPer
22

33
[![crates](https://img.shields.io/crates/v/phper?style=flat-square)](https://crates.io/crates/phper)
4-
[![](https://img.shields.io/docsrs/phper?style=flat-square)](https://docs.rs/phper)
4+
[![docs](https://img.shields.io/docsrs/phper?style=flat-square)](https://docs.rs/phper)
55

66
A library that allows us to write PHP extensions using pure Rust and using safe Rust whenever possible.
77

phper-sys/php_wrapper.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,7 @@ void phper_zend_hash_merge_with_key(HashTable *target, HashTable *source) {
115115
void phper_zval_obj(zval *z, zend_object *o) {
116116
ZVAL_OBJ(z, o);
117117
}
118+
119+
int phper_z_type_info_refcounted(uint32_t t) {
120+
return Z_TYPE_INFO_REFCOUNTED(t);
121+
}

phper-sys/php_wrapper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,6 @@ 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);
45+
4446
#endif //PHPER_PHP_WRAPPER_H

phper/src/arrays.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
//! Apis relate to [crate::sys::zend_array].
2+
13
use crate::{sys::*, values::Val};
4+
use phper_alloc::EBox;
25
use std::mem::zeroed;
36

47
#[repr(transparent)]
@@ -28,14 +31,15 @@ impl Array {
2831
&mut self.inner
2932
}
3033

31-
pub fn insert(&mut self, key: impl AsRef<str>, mut value: Val) {
34+
pub fn insert(&mut self, key: impl AsRef<str>, value: Val) {
3235
let key = key.as_ref();
36+
let value = EBox::new(value);
3337
unsafe {
3438
phper_zend_hash_str_update(
3539
&mut self.inner,
3640
key.as_ptr().cast(),
3741
key.len(),
38-
value.as_mut_ptr(),
42+
EBox::into_raw(value).cast(),
3943
);
4044
}
4145
}

phper/src/functions.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ pub(crate) unsafe extern "C" fn invoke(
163163
execute_data.common_required_num_args(),
164164
execute_data.num_args()
165165
);
166-
return_value.set(());
166+
SetVal::set_val((), return_value);
167167
return;
168168
}
169169

@@ -178,11 +178,7 @@ pub(crate) unsafe extern "C" fn invoke(
178178
let this = this.as_mut().expect("this should not be null");
179179
// TODO Fix the object type assertion.
180180
// assert!(this.get_type().is_object());
181-
m.call(
182-
Object::from_mut_ptr(this.inner.value.obj),
183-
&mut arguments,
184-
return_value,
185-
);
181+
m.call(this.as_mut_object_unchecked(), &mut arguments, return_value);
186182
}
187183
}
188184
}

phper/src/lib.rs

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,8 @@
11
#![warn(rust_2018_idioms, clippy::dbg_macro, clippy::print_stdout)]
22

33
/*!
4-
# PHPer
5-
6-
[![crates](https://img.shields.io/crates/v/phper?style=flat-square)](https://crates.io/crates/phper)
7-
[![](https://img.shields.io/docsrs/phper?style=flat-square)](https://docs.rs/phper)
8-
94
A library that allows us to write PHP extensions using pure Rust and using safe Rust whenever possible.
105
11-
## Requirement
12-
13-
### Necessary
14-
15-
**libclang** version >= 9
16-
17-
**php** version >= 7
18-
19-
### Tested Support
20-
21-
**os**
22-
23-
- linux
24-
25-
**php**
26-
27-
*version*
28-
29-
- 7.0
30-
- 7.1
31-
- 7.2
32-
- 7.3
33-
- 7.4
34-
- 8.0
35-
36-
*mode*
37-
38-
- nts
39-
40-
*sapi*
41-
42-
- cli
43-
446
## Usage
457
468
1. Make sure `libclang` and `php` is installed.
@@ -68,7 +30,7 @@ phper = "0.2"
6830
6931
4. Add these code to `main.rs`.
7032
71-
```rust,no_run
33+
```no_run
7234
use phper::cmd::make;
7335
7436
fn main() {

phper/src/types.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ impl Type {
6969
pub fn is_object(self) -> bool {
7070
matches!(self, Type::Object | Type::ObjectEx)
7171
}
72+
73+
#[inline]
74+
pub fn is_ref_counted(self) -> bool {
75+
unsafe { phper_z_type_info_refcounted(self as u32) != 0 }
76+
}
7277
}
7378

7479
impl From<u32> for Type {

phper/src/values.rs

Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Apis relate to [crate::sys::zval].
2+
13
use crate::{
24
alloc::EBox,
35
arrays::Array,
@@ -14,6 +16,7 @@ use std::{
1416
sync::atomic::Ordering,
1517
};
1618

19+
/// Wrapper of [crate::sys::zend_execute_data].
1720
#[repr(transparent)]
1821
pub struct ExecuteData {
1922
inner: zend_execute_data,
@@ -66,18 +69,23 @@ impl ExecuteData {
6669
}
6770
}
6871

72+
/// Wrapper of [crate::sys::zval].
6973
#[repr(transparent)]
7074
pub struct Val {
71-
pub(crate) inner: zval,
75+
inner: zval,
7276
}
7377

7478
impl Val {
7579
pub fn new<T: SetVal>(t: T) -> Self {
76-
let mut val = Self::empty();
77-
val.set(t);
80+
let mut val = unsafe { zeroed::<Val>() };
81+
SetVal::set_val(t, &mut val);
7882
val
7983
}
8084

85+
pub fn null() -> Self {
86+
Self::new(())
87+
}
88+
8189
#[inline]
8290
pub const fn from_inner(inner: zval) -> Self {
8391
Self { inner }
@@ -88,40 +96,11 @@ impl Val {
8896
&mut *(ptr as *mut Self)
8997
}
9098

91-
#[inline]
92-
pub(crate) fn empty() -> Self {
93-
Self {
94-
inner: unsafe { zeroed::<zval>() },
95-
}
96-
}
97-
98-
pub fn null() -> Self {
99-
let mut val = Self::empty();
100-
val.set(());
101-
val
102-
}
103-
104-
pub fn from_bool(b: bool) -> Self {
105-
let mut val = Self::empty();
106-
val.set(b);
107-
val
108-
}
109-
110-
pub fn from_val(other: Val) -> Self {
111-
let mut val = Self::empty();
112-
val.set(other);
113-
val
114-
}
115-
11699
#[inline]
117100
pub fn as_mut_ptr(&mut self) -> *mut zval {
118101
&mut self.inner
119102
}
120103

121-
pub fn set(&mut self, v: impl SetVal) {
122-
v.set_val(self);
123-
}
124-
125104
pub fn get_type(&self) -> Type {
126105
let t = unsafe { self.inner.u1.type_info };
127106
t.into()
@@ -211,6 +190,10 @@ impl Val {
211190
}
212191
}
213192

193+
pub(crate) unsafe fn as_mut_object_unchecked(&self) -> &mut Object {
194+
Object::from_mut_ptr(self.inner.value.obj)
195+
}
196+
214197
fn must_be_type_error(&self, expect_type: &str) -> crate::Error {
215198
match self.get_type_name() {
216199
Ok(type_name) => {
@@ -223,28 +206,22 @@ impl Val {
223206
}
224207

225208
impl Drop for Val {
226-
// TODO Write the drop.
227209
fn drop(&mut self) {
228-
// let t = self.get_type();
229-
// unsafe {
230-
// if t.is_string() {
231-
// phper_zend_string_release(self.inner.value.str);
232-
// drop(EBox::from_raw(self.inner.value.str))
233-
// } else if t.is_array() {
234-
// zend_hash_destroy(self.inner.value.arr);
235-
// drop(EBox::from_raw(self.inner.value.arr))
236-
// } else if t.is_object() {
237-
// zend_objects_destroy_object(self.inner.value.obj);
238-
// drop(EBox::from_raw(self.inner.value.obj))
239-
// }
240-
// }
210+
let t = self.get_type();
211+
unsafe {
212+
if t.is_string() {
213+
phper_zend_string_release(self.inner.value.str);
214+
} else if t.is_array() {
215+
zend_hash_destroy(self.inner.value.arr);
216+
} else if t.is_object() {
217+
zend_objects_destroy_object(self.inner.value.obj);
218+
}
219+
}
241220
}
242221
}
243222

244223
/// The trait for setting the value of [Val], mainly as the return value of
245224
/// [crate::functions::Function] and [crate::functions::Method], and initializer of [Val].
246-
///
247-
/// TODO Fix the possibility of leak memory.
248225
pub trait SetVal {
249226
fn set_val(self, val: &mut Val);
250227
}
@@ -312,10 +289,11 @@ impl<T: SetVal> SetVal for Vec<T> {
312289
unsafe {
313290
phper_array_init(val.as_mut_ptr());
314291
for (k, v) in self.into_iter().enumerate() {
292+
let v = EBox::new(Val::new(v));
315293
phper_zend_hash_index_update(
316294
(*val.as_mut_ptr()).value.arr,
317295
k as u64,
318-
Val::new(v).as_mut_ptr(),
296+
EBox::into_raw(v).cast(),
319297
);
320298
}
321299
}
@@ -347,11 +325,12 @@ where
347325
phper_array_init(val.as_mut_ptr());
348326
for (k, v) in iterator.into_iter() {
349327
let k = k.as_ref();
328+
let v = EBox::new(Val::new(v));
350329
phper_zend_hash_str_update(
351330
(*val.as_mut_ptr()).value.arr,
352331
k.as_ptr().cast(),
353332
k.len(),
354-
Val::new(v).as_mut_ptr(),
333+
EBox::into_raw(v).cast(),
355334
);
356335
}
357336
}
@@ -406,7 +385,7 @@ impl<T: SetVal, E: Throwable> SetVal for Result<T, E> {
406385
impl SetVal for Val {
407386
fn set_val(mut self, val: &mut Val) {
408387
unsafe {
409-
phper_zval_copy_value(val.as_mut_ptr(), self.as_mut_ptr());
388+
phper_zval_copy(val.as_mut_ptr(), self.as_mut_ptr());
410389
}
411390
}
412391
}

tests/integration/src/values.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ fn integrate_returns(module: &mut Module) {
107107
integration_values_return_result_string_err,
108108
vec![],
109109
);
110+
module.add_function(
111+
"integration_values_return_val",
112+
integration_values_return_val,
113+
vec![],
114+
);
110115
}
111116

112117
fn integration_values_return_null(_: &mut [Val]) {}
@@ -203,3 +208,7 @@ fn integration_values_return_result_string_ok(_: &mut [Val]) -> phper::Result<St
203208
fn integration_values_return_result_string_err(_: &mut [Val]) -> phper::Result<()> {
204209
Err(phper::Error::other("a zhe"))
205210
}
211+
212+
fn integration_values_return_val(_: &mut [Val]) -> Val {
213+
Val::new("foo")
214+
}

tests/integration/tests/php/values.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@
2222
assert_eq(integration_values_return_option_i64_none(), null);
2323
assert_eq(integration_values_return_result_string_ok(), "foo");
2424
assert_throw("integration_values_return_result_string_err", "Phper\\OtherException", 500, "a zhe");
25+
assert_eq(integration_values_return_val(), "foo");

0 commit comments

Comments
 (0)