Skip to content

Commit

Permalink
Refactor ZendHashTable and Zval (#76)
Browse files Browse the repository at this point in the history
* Call zval destructor when changing zval type and dropping

* Remove zval return from array insert functions #73

The functions actually returned references to the new zval value, so
there's not much point in returning.

* Remove `ZendHashTable` wrapper

Replaced by returning references to the actual hashtable, and having a
new type `OwnedHashTable` when creating a new hashtable.

* Remove pointless `drop` field from `OwnedHashTable`

* Added `Values` iterator for Zend hashtable

* Change iterators to double ended and exact size
  • Loading branch information
davidcole1340 authored Sep 21, 2021
1 parent ff231ec commit 7c484a0
Show file tree
Hide file tree
Showing 11 changed files with 562 additions and 528 deletions.
2 changes: 2 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,4 +313,6 @@ const ALLOWED_BINDINGS: &[&str] = &[
"_ZEND_TYPE_NULLABLE_BIT",
"ts_rsrc_id",
"_ZEND_TYPE_NAME_BIT",
"zval_ptr_dtor",
"zend_refcounted_h",
];
114 changes: 7 additions & 107 deletions example/skel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,125 +1,25 @@
mod allocator;

use allocator::PhpAllocator;
use ext_php_rs::{
parse_args,
php::{
args::Arg,
enums::DataType,
exceptions::PhpException,
execution_data::ExecutionData,
function::FunctionBuilder,
types::{
array::OwnedHashTable,
callable::Callable,
closure::Closure,
object::{ClassObject, ClassRef},
zval::{FromZval, IntoZval, Zval},
},
},
php_class,
prelude::*,
};

// #[php_function]
// pub fn hello_world() -> String {
// let call = Callable::try_from_name("strpos").unwrap();

// eprintln!("im callin");
// let val = call.try_call(vec![&"hello world", &"w"]);
// dbg!(val);
// "Ok".into()
// }

// #[php_const]
// const SKEL_TEST_CONST: &str = "Test constant";
// #[php_const]
// const SKEL_TEST_LONG_CONST: i32 = 1234;

// #[php_function(optional = "z")]
// pub fn skeleton_version(x: ZendHashTable, y: f64, z: Option<f64>) -> String {
// dbg!(x, y, z);
// "Hello".into()
// }

// #[php_function(optional = "z")]
// pub fn skeleton_array(
// arr: ZendHashTable,
// x: i32,
// y: f64,
// z: Option<f64>,
// ) -> Result<ZendHashTable, String> {
// for (k, x, y) in arr.iter() {
// println!("{:?} {:?} {:?}", k, x, y.string());
// }

// dbg!(x, y, z);

// let mut new = ZendHashTable::new();
// new.insert("Hello", &"World")
// .map_err(|_| "Couldn't insert into hashtable")?;
// Ok(new)
// }

// #[php_function(optional = "i", defaults(i = 5))]
// pub fn test_array(i: i32, b: Option<i32>) -> Vec<i32> {
// dbg!(i, b);
// vec![1, 2, 3, 4]
// }

// #[php_function(optional = "offset", defaults(offset = 0))]
// pub fn rust_strpos(haystack: &str, needle: &str, offset: i64) -> Option<usize> {
// let haystack = haystack.chars().skip(offset as usize).collect::<String>();
// haystack.find(needle)
// }

// #[php_function]
// pub fn example_exception() -> Result<i32, &'static str> {
// Err("Bad here")
// }

// #[php_function]
// pub fn skel_unpack<'a>(
// mut arr: HashMap<String, String>,
// ) -> Result<HashMap<String, String>, PhpException<'a>> {
// arr.insert("hello".into(), "not world".into());
// Ok(arr)
// }

// #[php_function]
// pub fn test_extern() -> i32 {
// // let y = unsafe { strpos("hello", "e", None) };
// // dbg!(y);
// // let x = unsafe { test_func() };
// // dbg!(x.try_call(vec![]));
// 0
// }

// #[php_function]
// pub fn test_lifetimes<'a>() -> ZendHashTable<'a> {
// ZendHashTable::try_from(&HashMap::<String, String>::new()).unwrap()
// }

#[php_function]
pub fn test_str(input: &str) -> &str {
input
}

// #[no_mangle]
// pub extern "C" fn php_module_info(_module: *mut ModuleEntry) {
// info_table_start!();
// info_table_row!("skeleton extension", "enabled");
// info_table_end!();
// }

// #[php_class(name = "Redis\\Exception\\RedisClientException")]
// #[extends(ClassEntry::exception())]
// #[derive(Default)]
// struct RedisException;

// #[php_function]
// pub fn test_exception() -> Result<i32, PhpException<'static>> {
// Err(PhpException::from_class::<RedisException>(
// "Hello world".into(),
// ))
// }

// #[global_allocator]
// static GLOBAL: PhpAllocator = PhpAllocator::new();

#[php_class]
#[property(test = 0)]
#[property(another = "Hello world")]
Expand Down
17 changes: 9 additions & 8 deletions example/skel/test.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
<?php

include 'vendor/autoload.php';
test_zval(['hello' => 'world']);
//include 'vendor/autoload.php';

$ext = new ReflectionExtension('skel');
//$ext = new ReflectionExtension('skel');

dd($ext);
//dd($ext);

$x = fn_once();
$x();
$x();
//$x = fn_once();
//$x();
//$x();

// $x = get_closure();
//// $x = get_closure();

// var_dump($x(5));
//// var_dump($x(5));
12 changes: 5 additions & 7 deletions src/php/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,13 @@ impl TryFrom<ZvalTypeFlags> for DataType {
}
}

impl TryFrom<u32> for DataType {
type Error = Error;

impl From<u32> for DataType {
#[allow(clippy::bad_bit_mask)]
fn try_from(value: u32) -> Result<Self> {
fn from(value: u32) -> Self {
macro_rules! contains {
($c: ident, $t: ident) => {
if (value & $c) == $c {
return Ok(DataType::$t);
return DataType::$t;
}
};
}
Expand All @@ -134,12 +132,12 @@ impl TryFrom<u32> for DataType {
contains!(IS_NULL, Null);

if (value & IS_OBJECT) == IS_OBJECT {
return Ok(DataType::Object(None));
return DataType::Object(None);
}

contains!(IS_UNDEF, Undef);

Err(Error::UnknownDatatype(value))
DataType::Mixed
}
}

Expand Down
10 changes: 3 additions & 7 deletions src/php/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::bindings::{_zend_executor_globals, ext_php_rs_executor_globals};

use super::types::array::ZendHashTable;
use super::types::array::HashTable;

/// Stores global variables used in the PHP executor.
pub type ExecutorGlobals = _zend_executor_globals;
Expand All @@ -17,11 +17,7 @@ impl ExecutorGlobals {
}

/// Attempts to retrieve the global class hash table.
pub fn class_table(&self) -> Option<ZendHashTable> {
if self.class_table.is_null() {
return None;
}

unsafe { ZendHashTable::from_ptr(self.class_table, false) }.ok()
pub fn class_table(&self) -> Option<&HashTable> {
unsafe { self.class_table.as_ref() }
}
}
Loading

0 comments on commit 7c484a0

Please sign in to comment.