Skip to content

Commit f506a41

Browse files
Pass class object type to PHP when taking object parameter (#64)
* Pass class object type to PHP when taking object parameter * Fix test * Update docs.rs stub bindings
1 parent 8b3ed08 commit f506a41

File tree

13 files changed

+186
-56
lines changed

13 files changed

+186
-56
lines changed

build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,4 +312,5 @@ const ALLOWED_BINDINGS: &[&str] = &[
312312
"_ZEND_SEND_MODE_SHIFT",
313313
"_ZEND_TYPE_NULLABLE_BIT",
314314
"ts_rsrc_id",
315+
"_ZEND_TYPE_NAME_BIT",
315316
];

docsrs_bindings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
1515
pub const ZEND_DEBUG: u32 = 1;
1616
pub const ZEND_MM_ALIGNMENT: u32 = 8;
17+
pub const _ZEND_TYPE_NAME_BIT: u32 = 8388608;
1718
pub const _ZEND_TYPE_NULLABLE_BIT: u32 = 2;
1819
pub const HT_MIN_SIZE: u32 = 8;
1920
pub const IS_UNDEF: u32 = 0;

example/skel/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ pub fn test_str(input: &str) -> &str {
117117
// ))
118118
// }
119119

120-
#[global_allocator]
121-
static GLOBAL: PhpAllocator = PhpAllocator::new();
120+
// #[global_allocator]
121+
// static GLOBAL: PhpAllocator = PhpAllocator::new();
122122

123123
#[php_class]
124124
#[property(test = 0)]

example/skel/test.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
<?php
22

3+
include 'vendor/autoload.php';
4+
5+
$ext = new ReflectionExtension('skel');
6+
7+
dd($ext);
8+
39
$x = fn_once();
410
$x();
511
$x();

ext-php-rs-derive/src/class.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ pub fn parser(args: AttributeArgs, mut input: ItemStruct) -> Result<TokenStream>
7575
static #meta: ::ext_php_rs::php::types::object::ClassMetadata<#ident> = ::ext_php_rs::php::types::object::ClassMetadata::new();
7676

7777
impl ::ext_php_rs::php::types::object::RegisteredClass for #ident {
78+
const CLASS_NAME: &'static str = #class_name;
79+
7880
fn get_metadata() -> &'static ::ext_php_rs::php::types::object::ClassMetadata<Self> {
7981
&#meta
8082
}

src/php/args.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ impl<'a> Arg<'a> {
118118
self.as_ref,
119119
self.variadic,
120120
self.allow_null,
121-
),
121+
)
122+
.ok_or(Error::InvalidCString)?,
122123
default_value: match &self.default_value {
123124
Some(val) => CString::new(val.as_str())?.into_raw(),
124125
None => ptr::null(),
@@ -135,7 +136,7 @@ impl From<Arg<'_>> for _zend_expected_type {
135136
DataType::Double => _zend_expected_type_Z_EXPECTED_DOUBLE,
136137
DataType::String => _zend_expected_type_Z_EXPECTED_STRING,
137138
DataType::Array => _zend_expected_type_Z_EXPECTED_ARRAY,
138-
DataType::Object => _zend_expected_type_Z_EXPECTED_OBJECT,
139+
DataType::Object(_) => _zend_expected_type_Z_EXPECTED_OBJECT,
139140
DataType::Resource => _zend_expected_type_Z_EXPECTED_RESOURCE,
140141
_ => unreachable!(),
141142
};

src/php/class.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,11 @@ impl ClassBuilder {
264264
///
265265
/// * `T` - The type which will override the Zend object. Must implement [`RegisteredClass`]
266266
/// which can be derived using the [`php_class`](crate::php_class) attribute macro.
267+
///
268+
/// # Panics
269+
///
270+
/// Panics if the class name associated with `T` is not the same as the class name specified
271+
/// when creating the builder.
267272
pub fn object_override<T: RegisteredClass>(mut self) -> Self {
268273
unsafe extern "C" fn create_object<T: RegisteredClass>(
269274
_: *mut ClassEntry,
@@ -272,6 +277,7 @@ impl ClassBuilder {
272277
(*ptr).get_mut_zend_obj()
273278
}
274279

280+
assert_eq!(self.name.as_str(), T::CLASS_NAME);
275281
self.object_override = Some(create_object::<T>);
276282
self
277283
}

src/php/enums.rs

Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,54 @@ use crate::{
1212
};
1313

1414
/// Valid data types for PHP.
15-
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
16-
#[repr(u32)]
15+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
1716
pub enum DataType {
18-
Undef = IS_UNDEF,
19-
20-
Null = IS_NULL,
21-
False = IS_FALSE,
22-
True = IS_TRUE,
23-
Long = IS_LONG,
24-
Double = IS_DOUBLE,
25-
String = IS_STRING,
26-
Array = IS_ARRAY,
27-
Object = IS_OBJECT,
28-
Resource = IS_RESOURCE,
29-
Reference = IS_REFERENCE,
30-
Callable = IS_CALLABLE,
31-
32-
ConstantExpression = IS_CONSTANT_AST,
33-
Void = IS_VOID,
34-
Mixed = IS_MIXED,
35-
36-
/// Only used when creating arguments.
37-
Bool = _IS_BOOL,
17+
Undef,
18+
Null,
19+
False,
20+
True,
21+
Long,
22+
Double,
23+
String,
24+
Array,
25+
Object(Option<&'static str>),
26+
Resource,
27+
Reference,
28+
Callable,
29+
ConstantExpression,
30+
Void,
31+
Mixed,
32+
Bool,
33+
}
34+
35+
impl Default for DataType {
36+
fn default() -> Self {
37+
Self::Void
38+
}
39+
}
40+
41+
impl DataType {
42+
/// Returns the integer representation of the data type.
43+
pub const fn as_u32(&self) -> u32 {
44+
match self {
45+
DataType::Undef => IS_UNDEF,
46+
DataType::Null => IS_NULL,
47+
DataType::False => IS_FALSE,
48+
DataType::True => IS_TRUE,
49+
DataType::Long => IS_LONG,
50+
DataType::Double => IS_DOUBLE,
51+
DataType::String => IS_STRING,
52+
DataType::Array => IS_ARRAY,
53+
DataType::Object(_) => IS_OBJECT,
54+
DataType::Resource => IS_RESOURCE,
55+
DataType::Reference => IS_RESOURCE,
56+
DataType::Callable => IS_CALLABLE,
57+
DataType::ConstantExpression => IS_CONSTANT_AST,
58+
DataType::Void => IS_VOID,
59+
DataType::Mixed => IS_MIXED,
60+
DataType::Bool => _IS_BOOL,
61+
}
62+
}
3863
}
3964

4065
// TODO: Ideally want something like this
@@ -69,12 +94,15 @@ impl TryFrom<ZvalTypeFlags> for DataType {
6994
contains!(Double);
7095
contains!(String);
7196
contains!(Array);
72-
contains!(Object);
7397
contains!(Resource);
7498
contains!(Callable);
7599
contains!(ConstantExpression);
76100
contains!(Void);
77101

102+
if value.contains(ZvalTypeFlags::Object) {
103+
return Ok(DataType::Object(None));
104+
}
105+
78106
Err(Error::UnknownDatatype(0))
79107
}
80108
}
@@ -95,18 +123,20 @@ impl TryFrom<u32> for DataType {
95123
contains!(IS_VOID, Void);
96124
contains!(IS_CALLABLE, Callable);
97125
contains!(IS_CONSTANT_AST, ConstantExpression);
98-
contains!(IS_CONSTANT_AST, ConstantExpression);
99-
contains!(IS_CONSTANT_AST, ConstantExpression);
100126
contains!(IS_REFERENCE, Reference);
101127
contains!(IS_RESOURCE, Resource);
102-
contains!(IS_OBJECT, Object);
103128
contains!(IS_ARRAY, Array);
104129
contains!(IS_STRING, String);
105130
contains!(IS_DOUBLE, Double);
106131
contains!(IS_LONG, Long);
107132
contains!(IS_TRUE, True);
108133
contains!(IS_FALSE, False);
109134
contains!(IS_NULL, Null);
135+
136+
if (value & IS_OBJECT) == IS_OBJECT {
137+
return Ok(DataType::Object(None));
138+
}
139+
110140
contains!(IS_UNDEF, Undef);
111141

112142
Err(Error::UnknownDatatype(value))
@@ -124,7 +154,7 @@ impl Display for DataType {
124154
DataType::Double => write!(f, "Double"),
125155
DataType::String => write!(f, "String"),
126156
DataType::Array => write!(f, "Array"),
127-
DataType::Object => write!(f, "Object"),
157+
DataType::Object(obj) => write!(f, "{}", obj.as_deref().unwrap_or("Object")),
128158
DataType::Resource => write!(f, "Resource"),
129159
DataType::Reference => write!(f, "Reference"),
130160
DataType::Callable => write!(f, "Callable"),
@@ -163,7 +193,7 @@ mod tests {
163193
test!(IS_DOUBLE, Double);
164194
test!(IS_STRING, String);
165195
test!(IS_ARRAY, Array);
166-
test!(IS_OBJECT, Object);
196+
assert_eq!(DataType::try_from(IS_OBJECT), Ok(DataType::Object(None)));
167197
test!(IS_RESOURCE, Resource);
168198
test!(IS_REFERENCE, Reference);
169199
test!(IS_CONSTANT_AST, ConstantExpression);
@@ -173,7 +203,7 @@ mod tests {
173203
test!(IS_INTERNED_STRING_EX, String);
174204
test!(IS_STRING_EX, String);
175205
test!(IS_ARRAY_EX, Array);
176-
test!(IS_OBJECT_EX, Object);
206+
assert_eq!(DataType::try_from(IS_OBJECT_EX), Ok(DataType::Object(None)));
177207
test!(IS_RESOURCE_EX, Resource);
178208
test!(IS_REFERENCE_EX, Reference);
179209
test!(IS_CONSTANT_AST_EX, ConstantExpression);

src/php/function.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
33
use std::{ffi::CString, mem, os::raw::c_char, ptr};
44

5-
use crate::bindings::zend_function_entry;
65
use crate::errors::Result;
6+
use crate::{bindings::zend_function_entry, errors::Error};
77

88
use super::{
99
args::{Arg, ArgInfo},
@@ -132,6 +132,7 @@ impl<'a> FunctionBuilder<'a> {
132132
type_: match self.retval {
133133
Some(retval) => {
134134
ZendType::empty_from_type(retval, self.ret_as_ref, false, self.ret_as_null)
135+
.ok_or(Error::InvalidCString)?
135136
}
136137
None => ZendType::empty(false, false),
137138
},

src/php/types/closure.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ impl Default for Closure {
151151
}
152152

153153
impl RegisteredClass for Closure {
154+
const CLASS_NAME: &'static str = "RustClosure";
155+
154156
fn get_metadata() -> &'static super::object::ClassMetadata<Self> {
155157
&CLOSURE_META
156158
}

0 commit comments

Comments
 (0)