Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ categories = ["api-bindings"]

[dependencies]
bitflags = "1.2.1"
parking_lot = "0.11.2"
ext-php-rs-derive = { version = "=0.4.0", path = "./ext-php-rs-derive" }

[build-dependencies]
Expand Down
1 change: 1 addition & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ fn main() {
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.rustfmt_bindings(true)
.no_copy("_zend_value")
.no_copy("_zend_string")
.layout_tests(env::var("EXT_PHP_RS_TEST").is_ok());

for binding in ALLOWED_BINDINGS.iter() {
Expand Down
7 changes: 6 additions & 1 deletion example/skel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,10 @@ pub fn closure_count() -> Closure {

#[php_module]
pub fn module(module: ModuleBuilder) -> ModuleBuilder {
module
module.function(
FunctionBuilder::new("test_zval", test_zval)
.arg(Arg::new("test", DataType::Array))
.build()
.unwrap(),
)
}
12 changes: 12 additions & 0 deletions example/skel/test.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
<?php

<<<<<<< HEAD
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to rebase this properly, but I'm going to delete example/skel soon as it's just my testbench at this point

<<<<<<< HEAD
<<<<<<< HEAD
test_zval(['hello' => 'world']);
=======
test_zval();
>>>>>>> 712aded56 (Call zval destructor when changing zval type and dropping)
=======
test_zval(['hello' => 'world']);
>>>>>>> 3646da741 (Remove `ZendHashTable` wrapper)
=======
test_zval([]);
>>>>>>> 7ba9ee9bf (Refactor `ZendString` into a borrowed and owned variant)
//include 'vendor/autoload.php';

//$ext = new ReflectionExtension('skel');
Expand Down
15 changes: 7 additions & 8 deletions src/php/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ impl ClassEntry {
/// not be found or the class table has not been initialized.
pub fn try_find(name: &str) -> Option<&'static Self> {
ExecutorGlobals::get().class_table()?;
let name = ZendString::new(name, false).ok()?;
let mut name = ZendString::new(name, false).ok()?;

unsafe {
crate::bindings::zend_lookup_class_ex(name.borrow_ptr(), std::ptr::null_mut(), 0)
crate::bindings::zend_lookup_class_ex(name.as_mut_zend_str(), std::ptr::null_mut(), 0)
.as_ref()
}
}
Expand Down Expand Up @@ -115,8 +115,7 @@ impl ClassEntry {
if self.flags().contains(ClassFlags::ResolvedParent) {
unsafe { self.__bindgen_anon_1.parent.as_ref() }
} else {
let name =
unsafe { ZendString::from_ptr(self.__bindgen_anon_1.parent_name, false) }.ok()?;
let name = unsafe { self.__bindgen_anon_1.parent_name.as_ref()? };
Self::try_find(name.as_str()?)
}
}
Expand Down Expand Up @@ -288,7 +287,7 @@ impl ClassBuilder {
///
/// Returns an [`Error`] variant if the class could not be registered.
pub fn build(mut self) -> Result<&'static mut ClassEntry> {
self.ptr.name = ZendString::new_interned(&self.name)?.release();
self.ptr.name = ZendString::new_interned(&self.name, true)?.into_inner();

self.methods.push(FunctionEntry::end());
let func = Box::into_raw(self.methods.into_boxed_slice()) as *const FunctionEntry;
Expand Down Expand Up @@ -349,9 +348,9 @@ impl ClassBuilder {

impl Debug for ClassEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let name: String = unsafe { ZendString::from_ptr(self.name, false) }
.and_then(|str| str.try_into())
.map_err(|_| std::fmt::Error)?;
let name: String = unsafe { self.name.as_ref() }
.and_then(|s| s.try_into().ok())
.ok_or(std::fmt::Error)?;

f.debug_struct("ClassEntry")
.field("name", &name)
Expand Down
19 changes: 8 additions & 11 deletions src/php/types/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@ use crate::{
php::enums::DataType,
};

use super::{
string::ZendString,
zval::{FromZval, IntoZval, Zval},
};
use super::zval::{FromZval, IntoZval, Zval};

/// PHP array, which is represented in memory as a hashtable.
pub use crate::bindings::HashTable;
Expand Down Expand Up @@ -239,9 +236,7 @@ impl<'a> Iterator for Iter<'a> {
}

let bucket = unsafe { pos.as_ref() };
let key = unsafe { ZendString::from_ptr(bucket.key, false) }
.and_then(|s| s.try_into())
.ok();
let key = unsafe { bucket.key.as_ref() }.and_then(|s| s.try_into().ok());

self.pos = NonNull::new(unsafe { pos.as_ptr().offset(1) });

Expand Down Expand Up @@ -272,9 +267,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> {

let new_end = NonNull::new(unsafe { end.as_ptr().offset(-1) })?;
let bucket = unsafe { new_end.as_ref() };
let key = unsafe { ZendString::from_ptr(bucket.key, false) }
.and_then(|s| s.try_into())
.ok();
let key = unsafe { bucket.key.as_ref() }.and_then(|s| s.try_into().ok());
self.end = Some(new_end);

Some((bucket.h, key, &bucket.val))
Expand Down Expand Up @@ -370,7 +363,11 @@ impl OwnedHashTable {
}
}

/// Returns the inner pointer to the hashtable, without destroying the
/// Converts the owned Zend hashtable into the internal pointer, bypassing the [`Drop`]
/// implementation.
///
/// The caller is responsible for freeing the resulting pointer using the `zend_array_destroy`
/// function.
pub fn into_inner(self) -> *mut HashTable {
let this = ManuallyDrop::new(self);
this.ptr.as_ptr()
Expand Down
25 changes: 12 additions & 13 deletions src/php/types/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,13 @@ pub enum PropertyQuery {
impl ZendObject {
/// Attempts to retrieve the class name of the object.
pub fn get_class_name(&self) -> Result<String> {
let name = unsafe {
ZendString::from_ptr(
self.handlers()?.get_class_name.ok_or(Error::InvalidScope)?(self),
false,
)
}?;

name.try_into()
unsafe {
self.handlers()?
.get_class_name
.and_then(|f| f(self).as_ref())
.ok_or(Error::InvalidScope)
.and_then(|s| s.try_into())
}
}

/// Checks if the given object is an instance of a registered class with Rust
Expand All @@ -74,13 +73,13 @@ impl ZendObject {
return Err(Error::InvalidProperty);
}

let name = ZendString::new(name, false)?;
let mut name = ZendString::new(name, false)?;
let mut rv = Zval::new();

unsafe {
self.handlers()?.read_property.ok_or(Error::InvalidScope)?(
self.mut_ptr(),
name.borrow_ptr(),
name.as_mut_zend_str(),
1,
std::ptr::null_mut(),
&mut rv,
Expand All @@ -98,13 +97,13 @@ impl ZendObject {
/// * `name` - The name of the property.
/// * `value` - The value to set the property to.
pub fn set_property(&mut self, name: &str, value: impl IntoZval) -> Result<&Zval> {
let name = ZendString::new(name, false)?;
let mut name = ZendString::new(name, false)?;
let mut value = value.into_zval(false)?;

unsafe {
self.handlers()?.write_property.ok_or(Error::InvalidScope)?(
self,
name.borrow_ptr(),
name.as_mut_zend_str(),
&mut value,
std::ptr::null_mut(),
)
Expand All @@ -127,7 +126,7 @@ impl ZendObject {
Ok(unsafe {
self.handlers()?.has_property.ok_or(Error::InvalidScope)?(
self.mut_ptr(),
name.borrow_ptr(),
name.deref() as *const _ as *mut _,
query as _,
std::ptr::null_mut(),
)
Expand Down
Loading