Skip to content

Commit 4efb8ed

Browse files
committed
Add intergation tests for Array and Object.
1 parent 8a557aa commit 4efb8ed

File tree

18 files changed

+231
-63
lines changed

18 files changed

+231
-63
lines changed

examples/hello/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ pub fn get_module() -> Module {
7676
foo_class.add_method(
7777
"setFoo",
7878
|this: &mut Object, arguments: &mut [Val]| -> phper::Result<()> {
79-
this.set_property("foo", arguments[0].as_string_value()?);
79+
this.set_property("foo", Val::new(arguments[0].as_string_value()?));
8080
Ok(())
8181
},
8282
vec![Argument::by_val("foo")],

phper-alloc/src/lib.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,22 @@ use std::{
1313
ops::{Deref, DerefMut},
1414
};
1515

16+
pub trait EAllocatable {
17+
fn free(ptr: *mut Self) {
18+
unsafe {
19+
_efree(ptr.cast());
20+
}
21+
}
22+
}
23+
1624
/// The Box which use php `emalloc` and `efree` to manage memory.
1725
///
1826
/// TODO now feature `allocator_api` is still unstable, implement myself.
19-
pub struct EBox<T> {
27+
pub struct EBox<T: EAllocatable> {
2028
ptr: *mut T,
2129
}
2230

23-
impl<T> EBox<T> {
31+
impl<T: EAllocatable> EBox<T> {
2432
pub fn new(x: T) -> Self {
2533
unsafe {
2634
let ptr: *mut T = _emalloc(size_of::<T>()).cast();
@@ -40,24 +48,22 @@ impl<T> EBox<T> {
4048
}
4149
}
4250

43-
impl<T> Deref for EBox<T> {
51+
impl<T: EAllocatable> Deref for EBox<T> {
4452
type Target = T;
4553

4654
fn deref(&self) -> &Self::Target {
4755
unsafe { self.ptr.as_ref().unwrap() }
4856
}
4957
}
5058

51-
impl<T> DerefMut for EBox<T> {
59+
impl<T: EAllocatable> DerefMut for EBox<T> {
5260
fn deref_mut(&mut self) -> &mut Self::Target {
5361
unsafe { self.ptr.as_mut().unwrap() }
5462
}
5563
}
5664

57-
impl<T> Drop for EBox<T> {
65+
impl<T: EAllocatable> Drop for EBox<T> {
5866
fn drop(&mut self) {
59-
unsafe {
60-
_efree(self.ptr.cast());
61-
}
67+
<T>::free(self.ptr);
6268
}
6369
}

phper/src/arrays.rs

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,38 @@
11
//! Apis relate to [crate::sys::zend_array].
22
3-
use crate::{sys::*, values::Val};
4-
use phper_alloc::EBox;
3+
use crate::{
4+
alloc::{EAllocatable, EBox},
5+
sys::*,
6+
values::Val,
7+
};
58
use std::mem::zeroed;
69

10+
/// Key for [Array].
11+
pub enum Key<'a> {
12+
Index(u64),
13+
Str(&'a str),
14+
}
15+
16+
impl From<u64> for Key<'_> {
17+
fn from(i: u64) -> Self {
18+
Key::Index(i)
19+
}
20+
}
21+
22+
impl<'a> From<&'a str> for Key<'a> {
23+
fn from(s: &'a str) -> Self {
24+
Key::Str(s)
25+
}
26+
}
27+
28+
/// Wrapper of [crate::sys::zend_array].
729
#[repr(transparent)]
830
pub struct Array {
931
inner: zend_array,
1032
}
1133

1234
impl Array {
35+
// TODO Change to EBox<Self>.
1336
pub fn new() -> Self {
1437
unsafe {
1538
let mut array = zeroed::<Array>();
@@ -31,25 +54,38 @@ impl Array {
3154
&mut self.inner
3255
}
3356

34-
// TODO key should be int or string.
35-
pub fn insert(&mut self, key: impl AsRef<str>, value: Val) {
36-
let key = key.as_ref();
57+
pub fn insert<'a>(&mut self, key: impl Into<Key<'a>>, value: Val) {
58+
let key = key.into();
3759
let value = EBox::new(value);
3860
unsafe {
39-
phper_zend_hash_str_update(
40-
&mut self.inner,
41-
key.as_ptr().cast(),
42-
key.len(),
43-
EBox::into_raw(value).cast(),
44-
);
61+
match key {
62+
Key::Index(i) => {
63+
zend_hash_index_update(&mut self.inner, i, EBox::into_raw(value).cast());
64+
}
65+
Key::Str(s) => {
66+
phper_zend_hash_str_update(
67+
&mut self.inner,
68+
s.as_ptr().cast(),
69+
s.len(),
70+
EBox::into_raw(value).cast(),
71+
);
72+
}
73+
}
4574
}
4675
}
4776

48-
pub fn get(&mut self, key: impl AsRef<str>) -> &mut Val {
49-
let key = key.as_ref();
77+
pub fn get<'a>(&self, key: impl Into<Key<'a>>) -> Option<&Val> {
78+
let key = key.into();
5079
unsafe {
51-
let value = zend_hash_str_find(&mut self.inner, key.as_ptr().cast(), key.len());
52-
Val::from_mut_ptr(value)
80+
let value = match key {
81+
Key::Index(i) => zend_hash_index_find(&self.inner, i),
82+
Key::Str(s) => zend_hash_str_find(&self.inner, s.as_ptr().cast(), s.len()),
83+
};
84+
if value.is_null() {
85+
None
86+
} else {
87+
Some(Val::from_mut_ptr(value))
88+
}
5389
}
5490
}
5591

@@ -58,6 +94,14 @@ impl Array {
5894
}
5995
}
6096

97+
impl EAllocatable for Array {
98+
fn free(ptr: *mut Self) {
99+
unsafe {
100+
zend_hash_destroy(ptr.cast());
101+
}
102+
}
103+
}
104+
61105
impl Drop for Array {
62106
fn drop(&mut self) {
63107
unsafe {

phper/src/classes.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
//! Apis relate to [crate::sys::zend_class_entry].
2+
13
use crate::{
4+
errors::ClassNotFoundError,
25
functions::{Argument, Callable, FunctionEntity, FunctionEntry, Method},
36
sys::*,
47
utils::ensure_end_with_zero,
5-
ClassNotFoundError,
68
};
79
use once_cell::sync::OnceCell;
810
use std::{

phper/src/cmd.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Command tools for build, test and install extension process.
2+
13
use crate::sys::PHP_EXTENSION_DIR;
24
use anyhow::Context;
35
use clap::Clap;
@@ -23,6 +25,16 @@ enum SubCommand {
2325
#[derive(Clap)]
2426
struct InstallCommand {}
2527

28+
/// Make.
29+
///
30+
/// # Examples
31+
/// ```
32+
/// use phper::cmd::make;
33+
///
34+
/// fn main() {
35+
/// make();
36+
/// }
37+
/// ```
2638
pub fn make() {
2739
try_make().expect("make failed");
2840
}

phper/src/functions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ pub(crate) unsafe extern "C" fn invoke(
180180
execute_data: *mut zend_execute_data,
181181
return_value: *mut zval,
182182
) {
183-
let execute_data = ExecuteData::from_mut(execute_data);
183+
let execute_data = ExecuteData::from_mut_ptr(execute_data);
184184
let return_value = Val::from_mut_ptr(return_value);
185185

186186
let num_args = execute_data.common_num_args();

phper/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ mod macros;
9696
pub mod arrays;
9797
pub mod classes;
9898
pub mod cmd;
99-
mod errors;
99+
pub mod errors;
100100
pub mod functions;
101101
pub mod ini;
102102
pub mod modules;
@@ -107,7 +107,7 @@ pub mod types;
107107
mod utils;
108108
pub mod values;
109109

110-
pub use crate::errors::*;
110+
pub use crate::errors::{Error, Result};
111111
pub use phper_alloc as alloc;
112112
pub use phper_macros::*;
113113
pub use phper_sys as sys;

phper/src/modules.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use crate::{
22
c_str_ptr,
33
classes::{Class, ClassEntity, StdClass},
4+
errors::EXCEPTION_CLASS_NAME,
45
functions::{Argument, Callable, Function, FunctionEntity},
56
ini::{IniEntity, IniValue, Policy, StrPtrBox},
67
sys::*,
78
utils::ensure_end_with_zero,
8-
EXCEPTION_CLASS_NAME,
99
};
1010
use std::{
1111
borrow::BorrowMut,

phper/src/objects.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use crate::{
2+
alloc::{EAllocatable, EBox},
23
classes::ClassEntry,
4+
errors::ClassNotFoundError,
35
sys::*,
46
values::{SetVal, Val},
5-
ClassNotFoundError,
67
};
7-
use phper_alloc::EBox;
88
use std::{
99
mem::{forget, zeroed},
1010
ptr::null_mut,
@@ -17,21 +17,21 @@ pub struct Object {
1717
}
1818

1919
impl Object {
20-
pub fn new(class_entry: &ClassEntry) -> Self {
20+
pub fn new(class_entry: &ClassEntry) -> EBox<Self> {
2121
unsafe {
22-
let mut object = zeroed::<Object>();
23-
zend_object_std_init(object.as_mut_ptr(), class_entry.as_ptr() as *mut _);
24-
object.inner.handlers = &std_object_handlers;
25-
object
22+
let ptr = zend_objects_new(class_entry.as_ptr() as *mut _);
23+
EBox::from_raw(ptr.cast())
2624
}
2725
}
2826

29-
pub fn new_by_class_name(class_name: impl AsRef<str>) -> Result<Self, ClassNotFoundError> {
27+
pub fn new_by_class_name(
28+
class_name: impl AsRef<str>,
29+
) -> Result<EBox<Self>, ClassNotFoundError> {
3030
let class_entry = ClassEntry::from_globals(class_name)?;
3131
Ok(Self::new(class_entry))
3232
}
3333

34-
pub fn new_by_std_class() -> Self {
34+
pub fn new_by_std_class() -> EBox<Self> {
3535
Self::new_by_class_name("stdclass").unwrap()
3636
}
3737

@@ -49,7 +49,7 @@ impl Object {
4949
&mut self.inner
5050
}
5151

52-
pub fn get_property(&self, name: impl AsRef<str>) -> &mut Val {
52+
pub fn get_property(&self, name: impl AsRef<str>) -> &Val {
5353
let name = name.as_ref();
5454

5555
let prop = unsafe {
@@ -82,9 +82,9 @@ impl Object {
8282
unsafe { Val::from_mut_ptr(prop) }
8383
}
8484

85-
pub fn set_property(&mut self, name: impl AsRef<str>, value: impl SetVal) {
85+
pub fn set_property(&mut self, name: impl AsRef<str>, val: Val) {
8686
let name = name.as_ref();
87-
let mut val = Val::new(value);
87+
let val = EBox::new(val);
8888
unsafe {
8989
#[cfg(phper_major_version = "8")]
9090
{
@@ -93,7 +93,7 @@ impl Object {
9393
&mut self.inner,
9494
name.as_ptr().cast(),
9595
name.len(),
96-
val.as_mut_ptr(),
96+
EBox::into_raw(val).cast(),
9797
)
9898
}
9999
#[cfg(phper_major_version = "7")]
@@ -105,7 +105,7 @@ impl Object {
105105
&mut zv,
106106
name.as_ptr().cast(),
107107
name.len(),
108-
val.as_mut_ptr(),
108+
EBox::into_raw(val).cast(),
109109
)
110110
}
111111
}
@@ -119,10 +119,16 @@ impl Object {
119119
}
120120
}
121121

122-
impl Drop for Object {
123-
fn drop(&mut self) {
122+
impl EAllocatable for Object {
123+
fn free(ptr: *mut Self) {
124124
unsafe {
125-
zend_objects_destroy_object(&mut self.inner);
125+
zend_objects_destroy_object(ptr.cast());
126126
}
127127
}
128128
}
129+
130+
impl Drop for Object {
131+
fn drop(&mut self) {
132+
unreachable!("Allocation on the stack is not allowed")
133+
}
134+
}

phper/src/strings.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,4 @@ impl ZendString {
2222
pub fn as_mut_ptr(&mut self) -> *mut zend_string {
2323
&mut self.inner
2424
}
25-
26-
pub unsafe fn from_raw(s: *mut zend_string) -> EBox<ZendString> {
27-
EBox::from_raw(s.cast())
28-
}
2925
}

0 commit comments

Comments
 (0)