diff --git a/.gitignore b/.gitignore index 77f6cf1e..b1458856 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /.cargo /vendor core +compile_commands.json diff --git a/examples/http-server/tests/integration.rs b/examples/http-server/tests/integration.rs index 9a798e52..607796ca 100644 --- a/examples/http-server/tests/integration.rs +++ b/examples/http-server/tests/integration.rs @@ -9,6 +9,7 @@ // See the Mulan PSL v2 for more details. use axum::http::header::CONTENT_TYPE; +use hyper::StatusCode; use phper_test::{cli::test_long_term_php_script_with_condition, utils::get_lib_path}; use reqwest::blocking::Client; use std::{ @@ -39,6 +40,7 @@ fn test_php() { let client = Client::new(); for _ in 0..5 { let response = client.get("http://127.0.0.1:9000/").send().unwrap(); + assert_eq!(response.status(), StatusCode::OK); let content_type = response.headers().get(CONTENT_TYPE).unwrap(); assert_eq!(content_type, "text/plain"); let body = response.text().unwrap(); diff --git a/phper-alloc/src/lib.rs b/phper-alloc/src/lib.rs index 32b569fd..03381eba 100644 --- a/phper-alloc/src/lib.rs +++ b/phper-alloc/src/lib.rs @@ -12,85 +12,7 @@ #![warn(clippy::dbg_macro, clippy::print_stdout)] #![doc = include_str!("../README.md")] -#[macro_use] -mod macros; - -use phper_sys::*; -use std::{ - borrow::Borrow, - mem::{ManuallyDrop, size_of}, - ops::{Deref, DerefMut}, -}; - -/// The Box which use php `emalloc` and `efree` to manage memory. -/// -/// TODO Now feature `allocator_api` is still unstable, implement myself, use -/// Box later. -pub struct EBox { - ptr: *mut T, -} - -impl EBox { - /// Allocates heap memory using `emalloc` then places `x` into it. - /// - /// # Panic - /// - /// Panic if `size_of::()` equals zero. - #[allow(clippy::useless_conversion)] - pub fn new(x: T) -> Self { - unsafe { - assert_ne!(size_of::(), 0); - let ptr: *mut T = phper_emalloc(size_of::().try_into().unwrap()).cast(); - // TODO Deal with ptr is zero, when memory limit is reached. - ptr.write(x); - Self { ptr } - } - } - - /// Constructs from a raw pointer. - /// - /// # Safety - /// - /// Make sure the pointer is from `into_raw`, or created from `emalloc`. - pub unsafe fn from_raw(raw: *mut T) -> Self { - Self { ptr: raw } - } - - /// Consumes and returning a wrapped raw pointer. - /// - /// Will leak memory. - pub fn into_raw(b: EBox) -> *mut T { - ManuallyDrop::new(b).ptr - } - - /// Consumes the `EBox`, returning the wrapped value. - pub fn into_inner(self) -> T { - unsafe { self.ptr.read() } - } -} - -impl Deref for EBox { - type Target = T; - - fn deref(&self) -> &Self::Target { - unsafe { self.ptr.as_ref().unwrap() } - } -} - -impl DerefMut for EBox { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { self.ptr.as_mut().unwrap() } - } -} - -impl Drop for EBox { - fn drop(&mut self) { - unsafe { - self.ptr.drop_in_place(); - phper_efree(self.ptr.cast()); - } - } -} +use std::borrow::Borrow; /// Duplicate an object without deep copy, but to only add the refcount, for php /// refcount struct. diff --git a/phper-alloc/src/macros.rs b/phper-alloc/src/macros.rs deleted file mode 100644 index 399bfa77..00000000 --- a/phper-alloc/src/macros.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2022 PHPER Framework Team -// PHPER is licensed under Mulan PSL v2. -// You can use this software according to the terms and conditions of the Mulan -// PSL v2. You may obtain a copy of Mulan PSL v2 at: -// http://license.coscl.org.cn/MulanPSL2 -// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY -// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -// See the Mulan PSL v2 for more details. - -/// Wrapper of `EBox::new`. -/// -/// # Examples -/// -/// ```no_test -/// let _ = ebox!(1); -/// ``` -#[macro_export] -macro_rules! ebox { - ($arg:tt) => {{ $crate::EBox::new($arg) }}; -} diff --git a/phper-doc/doc/_05_internal_types/_01_z_str/index.md b/phper-doc/doc/_05_internal_types/_01_z_str/index.md index 501a9d4e..ab463ede 100644 --- a/phper-doc/doc/_05_internal_types/_01_z_str/index.md +++ b/phper-doc/doc/_05_internal_types/_01_z_str/index.md @@ -18,7 +18,7 @@ use phper::strings::ZString; let s = ZString::new("Hello world!"); // Will leak memory. -let ptr = s.into_raw(); +let ptr = ZString::into_raw(s); // retake pointer. let ss = unsafe { ZString::from_raw(ptr) }; diff --git a/phper-test/src/context.rs b/phper-test/src/context.rs index 269183f5..97ad26a8 100644 --- a/phper-test/src/context.rs +++ b/phper-test/src/context.rs @@ -82,7 +82,6 @@ impl Context { ContextCommand { cmd, args } } - #[cfg_attr(docsrs, doc(cfg(feature = "fpm")))] pub fn find_php_fpm(&self) -> Option { use std::ffi::OsStr; diff --git a/phper-test/src/lib.rs b/phper-test/src/lib.rs index e775c878..c6cbfe97 100644 --- a/phper-test/src/lib.rs +++ b/phper-test/src/lib.rs @@ -10,7 +10,7 @@ #![warn(rust_2018_idioms, missing_docs)] #![warn(clippy::dbg_macro, clippy::print_stdout)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc = include_str!("../README.md")] pub mod cli; diff --git a/phper/src/alloc.rs b/phper/src/alloc.rs new file mode 100644 index 00000000..f6bb4da3 --- /dev/null +++ b/phper/src/alloc.rs @@ -0,0 +1,98 @@ +// Copyright (c) 2025 PHPER Framework Team +// PHPER is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +//! Memory allocation utilities and boxed types for PHP values. + +pub use phper_alloc::{RefClone, ToRefOwned}; +use std::{ + borrow::{Borrow, BorrowMut}, + fmt::{self}, + mem::ManuallyDrop, + ops::{Deref, DerefMut}, +}; + +/// A smart pointer for PHP values allocated in the Zend Engine memory. +/// +/// `EBox` provides owned access to values allocated in PHP's memory +/// management system. It automatically handles deallocation when dropped, +/// ensuring proper cleanup of PHP resources. +pub struct EBox { + ptr: *mut T, +} + +impl EBox { + /// Constructs from a raw pointer. + /// + /// # Safety + /// + /// Make sure the pointer is from `into_raw`, or created from `emalloc`. + pub unsafe fn from_raw(raw: *mut T) -> Self { + Self { ptr: raw } + } + + /// Consumes and returning a wrapped raw pointer. + /// + /// Will leak memory. + pub fn into_raw(b: EBox) -> *mut T { + ManuallyDrop::new(b).ptr + } +} + +impl fmt::Debug for EBox { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl Deref for EBox { + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { self.ptr.as_ref().unwrap() } + } +} + +impl DerefMut for EBox { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { self.ptr.as_mut().unwrap() } + } +} + +impl Drop for EBox { + fn drop(&mut self) { + unsafe { + self.ptr.drop_in_place(); + } + } +} + +impl Borrow for EBox { + fn borrow(&self) -> &T { + unsafe { self.ptr.as_ref().unwrap() } + } +} + +impl BorrowMut for EBox { + fn borrow_mut(&mut self) -> &mut T { + unsafe { self.ptr.as_mut().unwrap() } + } +} + +impl AsRef for EBox { + fn as_ref(&self) -> &T { + unsafe { self.ptr.as_ref().unwrap() } + } +} + +impl AsMut for EBox { + fn as_mut(&mut self) -> &mut T { + unsafe { self.ptr.as_mut().unwrap() } + } +} diff --git a/phper/src/arrays.rs b/phper/src/arrays.rs index 0b855549..437d3bd7 100644 --- a/phper/src/arrays.rs +++ b/phper/src/arrays.rs @@ -10,14 +10,14 @@ //! Apis relate to [zend_array]. -use crate::{alloc::ToRefOwned, strings::ZStr, sys::*, values::ZVal}; +use crate::{alloc::EBox, strings::ZStr, sys::*, values::ZVal}; use derive_more::From; +use phper_alloc::ToRefOwned; use std::{ - borrow::Borrow, fmt::{self, Debug}, marker::PhantomData, mem::ManuallyDrop, - ops::{Deref, DerefMut}, + ops::Deref, ptr::null_mut, }; @@ -333,6 +333,14 @@ impl ZArr { } } +impl Drop for ZArr { + fn drop(&mut self) { + unsafe { + zend_array_destroy(self.as_mut_ptr()); + } + } +} + impl Debug for ZArr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { common_fmt(self, f, "ZArr") @@ -346,7 +354,7 @@ impl ToOwned for ZArr { unsafe { // TODO The source really immutable? let dest = phper_zend_array_dup(self.as_ptr() as *mut _); - ZArray::from_raw(dest) + ZArray::from_raw(dest.cast()) } } } @@ -359,16 +367,17 @@ impl ToRefOwned for ZArr { unsafe { phper_zval_arr(val.as_mut_ptr(), self.as_mut_ptr()); phper_z_addref_p(val.as_mut_ptr()); - ZArray::from_raw(val.as_mut_z_arr().unwrap().as_mut_ptr()) + ZArray::from_raw(val.as_mut_z_arr().unwrap().as_mut_ptr().cast()) } } } -/// Wrapper of [zend_array]. -#[repr(transparent)] -pub struct ZArray { - inner: *mut ZArr, -} +/// An owned PHP array value. +/// +/// `ZArray` represents an owned PHP array (hashtable) allocated in the Zend +/// Engine memory. It provides safe access to PHP array operations and +/// automatically manages memory cleanup. +pub type ZArray = EBox; impl ZArray { /// Creates an empty `ZArray`. @@ -384,40 +393,9 @@ impl ZArray { pub fn with_capacity(n: usize) -> Self { unsafe { let ptr = phper_zend_new_array(n.try_into().unwrap()); - Self::from_raw(ptr) + Self::from_raw(ptr.cast()) } } - - /// Create owned object From raw pointer, usually used in pairs with - /// `into_raw`. - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead to memory - /// problems. For example, a double-free may occur if the function is called - /// twice on the same raw pointer. - #[inline] - pub unsafe fn from_raw(ptr: *mut zend_array) -> Self { - unsafe { - Self { - inner: ZArr::from_mut_ptr(ptr), - } - } - } - - /// Consumes the `ZArray` and transfers ownership to a raw pointer. - /// - /// Failure to call [`ZArray::from_raw`] will lead to a memory leak. - #[inline] - pub fn into_raw(self) -> *mut zend_array { - ManuallyDrop::new(self).as_mut_ptr() - } -} - -impl Debug for ZArray { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - common_fmt(self, f, "ZArray") - } } impl Default for ZArray { @@ -426,40 +404,12 @@ impl Default for ZArray { } } -impl Deref for ZArray { - type Target = ZArr; - - fn deref(&self) -> &Self::Target { - unsafe { self.inner.as_ref().unwrap() } - } -} - -impl DerefMut for ZArray { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { self.inner.as_mut().unwrap() } - } -} - -impl Borrow for ZArray { - fn borrow(&self) -> &ZArr { - self.deref() - } -} - impl Clone for ZArray { fn clone(&self) -> Self { self.deref().to_owned() } } -impl Drop for ZArray { - fn drop(&mut self) { - unsafe { - zend_array_destroy(self.as_mut_ptr()); - } - } -} - /// Iterator key for [`ZArr::iter`] and [`ZArr::iter_mut`]. #[derive(Debug, Clone, PartialEq, From)] pub enum IterKey<'a> { diff --git a/phper/src/classes.rs b/phper/src/classes.rs index 4dbb769e..694c8a6d 100644 --- a/phper/src/classes.rs +++ b/phper/src/classes.rs @@ -147,7 +147,7 @@ impl ClassEntry { // day of debugging time here). let mut val = ManuallyDrop::new(val); let ptr = phper_z_obj_p(val.as_mut_ptr()); - Ok(ZObject::from_raw(ptr)) + Ok(ZObject::from_raw(ptr.cast())) } } } @@ -335,6 +335,7 @@ impl StateClass { self.as_class_entry() .new_object(arguments) .map(ZObject::into_raw) + .map(|ptr| ptr.cast()) .map(StateObject::::from_raw_object) } @@ -345,6 +346,7 @@ impl StateClass { self.as_class_entry() .init_object() .map(ZObject::into_raw) + .map(|ptr| ptr.cast()) .map(StateObject::::from_raw_object) } } diff --git a/phper/src/functions.rs b/phper/src/functions.rs index 44e8d671..0ab11199 100644 --- a/phper/src/functions.rs +++ b/phper/src/functions.rs @@ -651,7 +651,7 @@ impl ZFunc { pub fn get_function_or_method_name(&self) -> ZString { unsafe { let s = phper_get_function_or_method_name(self.as_ptr()); - ZString::from_raw(s) + ZString::from_raw(s.cast()) } } @@ -890,7 +890,7 @@ pub(crate) fn call_raw_common(call_fn: impl FnOnce(&mut ZVal)) -> crate::Result< if !eg!(exception).is_null() { #[allow(static_mut_refs)] let e = ptr::replace(&mut eg!(exception), null_mut()); - let obj = ZObject::from_raw(e); + let obj = ZObject::from_raw(e.cast()); match ThrowObject::new(obj) { Ok(e) => return Err(e.into()), Err(e) => return Err(e.into()), diff --git a/phper/src/lib.rs b/phper/src/lib.rs index 1a2800c5..7a7a6f97 100644 --- a/phper/src/lib.rs +++ b/phper/src/lib.rs @@ -16,6 +16,7 @@ #[macro_use] mod macros; +pub mod alloc; pub mod arrays; pub mod classes; pub(crate) mod constants; @@ -34,6 +35,5 @@ mod utils; pub mod values; pub use crate::errors::{Error, Result, ok}; -pub use phper_alloc as alloc; pub use phper_macros::*; pub use phper_sys as sys; diff --git a/phper/src/objects.rs b/phper/src/objects.rs index 5969772c..4cd6bcc7 100644 --- a/phper/src/objects.rs +++ b/phper/src/objects.rs @@ -11,6 +11,7 @@ //! Apis relate to [zend_object]. use crate::{ + alloc::EBox, classes::ClassEntry, functions::{ZFunc, call_internal, call_raw_common}, sys::*, @@ -19,7 +20,6 @@ use crate::{ use phper_alloc::{RefClone, ToRefOwned}; use std::{ any::Any, - borrow::Borrow, ffi::c_void, fmt::{self, Debug}, marker::PhantomData, @@ -266,6 +266,14 @@ impl ZObj { } } +impl Drop for ZObj { + fn drop(&mut self) { + unsafe { + phper_zend_object_release(self.as_mut_ptr()); + } + } +} + impl ToRefOwned for ZObj { type Owned = ZObject; @@ -274,7 +282,7 @@ impl ToRefOwned for ZObj { unsafe { phper_zval_obj(val.as_mut_ptr(), self.as_mut_ptr()); phper_z_addref_p(val.as_mut_ptr()); - ZObject::from_raw(val.as_mut_z_obj().unwrap().as_mut_ptr()) + ZObject::from_raw(val.as_mut_z_obj().unwrap().as_mut_ptr().cast()) } } } @@ -285,10 +293,12 @@ impl Debug for ZObj { } } -/// Wrapper of [zend_object]. -pub struct ZObject { - inner: *mut ZObj, -} +/// An owned PHP object value. +/// +/// `ZObject` represents an owned PHP object allocated in the Zend Engine +/// memory. It provides safe access to PHP object operations and automatically +/// manages memory cleanup. +pub type ZObject = EBox; impl ZObject { /// Another way to new object like [crate::classes::ClassEntry::new_object]. @@ -308,29 +318,6 @@ impl ZObject { pub fn new_by_std_class() -> Self { Self::new_by_class_name("stdclass", &mut []).unwrap() } - - /// Create owned object From raw pointer, usually used in pairs with - /// `into_raw`. - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead to memory - /// problems. For example, a double-free may occur if the function is called - /// twice on the same raw pointer. - #[inline] - pub unsafe fn from_raw(ptr: *mut zend_object) -> Self { - unsafe { - Self { - inner: ZObj::from_mut_ptr(ptr), - } - } - } - - /// Consumes and returning a wrapped raw pointer. - #[inline] - pub fn into_raw(self) -> *mut zend_object { - ManuallyDrop::new(self).as_mut_ptr() - } } impl RefClone for ZObject { @@ -340,40 +327,6 @@ impl RefClone for ZObject { } } -impl Deref for ZObject { - type Target = ZObj; - - fn deref(&self) -> &Self::Target { - unsafe { self.inner.as_ref().unwrap() } - } -} - -impl DerefMut for ZObject { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { self.inner.as_mut().unwrap() } - } -} - -impl Borrow for ZObject { - fn borrow(&self) -> &ZObj { - self.deref() - } -} - -impl Drop for ZObject { - fn drop(&mut self) { - unsafe { - phper_zend_object_release(self.as_mut_ptr()); - } - } -} - -impl Debug for ZObject { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - common_fmt(self, f, "ZObject") - } -} - pub(crate) type AnyState = *mut dyn Any; /// The object owned state, usually as the parameter of method handler. @@ -474,20 +427,17 @@ impl Debug for StateObj { } } -/// The object owned state, usually crated by -/// [StateClass](crate::classes::StateClass). -pub struct StateObject { - inner: *mut StateObj, -} +/// An owned PHP object with associated Rust state. +/// +/// `StateObject` represents an owned PHP object that contains additional +/// Rust state of type `T`. This allows embedding custom Rust data structures +/// within PHP objects while maintaining proper memory management and cleanup. +pub type StateObject = EBox>; impl StateObject { #[inline] pub(crate) fn from_raw_object(object: *mut zend_object) -> Self { - unsafe { - Self { - inner: StateObj::from_mut_object_ptr(object), - } - } + unsafe { Self::from_raw(StateObj::from_mut_object_ptr(object)) } } #[inline] @@ -497,7 +447,7 @@ impl StateObject { /// Converts into [ZObject]. pub fn into_z_object(self) -> ZObject { - unsafe { ZObject::from_raw(self.into_raw_object()) } + unsafe { ZObject::from_raw(self.into_raw_object().cast()) } } } @@ -520,34 +470,6 @@ impl StateObject { } } -impl Drop for StateObject { - fn drop(&mut self) { - unsafe { - drop(ZObject::from_raw(self.as_mut_ptr())); - } - } -} - -impl Deref for StateObject { - type Target = StateObj; - - fn deref(&self) -> &Self::Target { - unsafe { self.inner.as_ref().unwrap() } - } -} - -impl DerefMut for StateObject { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { self.inner.as_mut().unwrap() } - } -} - -impl Debug for StateObject { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - common_fmt(self, f, "StateObject") - } -} - fn common_fmt(this: &ZObj, f: &mut fmt::Formatter<'_>, name: &str) -> fmt::Result { let mut d = f.debug_struct(name); match this.get_class().get_name().to_c_str() { diff --git a/phper/src/strings.rs b/phper/src/strings.rs index 2a35046a..62d73aba 100644 --- a/phper/src/strings.rs +++ b/phper/src/strings.rs @@ -10,15 +10,13 @@ //! Apis relate to [zend_string]. -use crate::sys::*; +use crate::{alloc::EBox, sys::*}; use phper_alloc::ToRefOwned; use std::{ - borrow::{Borrow, Cow}, + borrow::Cow, ffi::{CStr, FromBytesWithNulError}, fmt::{self, Debug}, marker::PhantomData, - mem::forget, - ops::{Deref, DerefMut}, os::raw::c_char, slice::from_raw_parts, str::{self, Utf8Error}, @@ -137,6 +135,14 @@ impl ZStr { } } +impl Drop for ZStr { + fn drop(&mut self) { + unsafe { + phper_zend_string_release(self.as_mut_ptr()); + } + } +} + impl Debug for ZStr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { common_fmt(self, f, "ZStr") @@ -169,15 +175,17 @@ impl ToRefOwned for ZStr { fn to_ref_owned(&mut self) -> Self::Owned { unsafe { let ptr = phper_zend_string_copy(self.as_mut_ptr()); - ZString::from_raw(ptr) + ZString::from_raw(ptr.cast()) } } } -/// Like String, CString for [zend_string]. -pub struct ZString { - inner: *mut ZStr, -} +/// An owned PHP string value. +/// +/// `ZString` represents an owned PHP string (zend_string) allocated in the Zend +/// Engine memory. It provides safe access to PHP string operations and +/// automatically manages memory cleanup using reference counting. +pub type ZString = EBox; impl ZString { /// Creates a new zend string from a container of bytes. @@ -190,7 +198,7 @@ impl ZString { s.len().try_into().unwrap(), false.into(), ); - Self::from_raw(ptr) + Self::from_raw(ptr.cast()) } } @@ -201,41 +209,9 @@ impl ZString { let s = s.as_ref(); let ptr = phper_zend_string_init(s.as_ptr().cast(), s.len().try_into().unwrap(), true.into()); - Self::from_raw(ptr) + Self::from_raw(ptr.cast()) } } - - /// Create owned object From raw pointer, usually used in pairs with - /// `into_raw`. - /// - /// # Safety - /// - /// This function is unsafe because improper use may lead to memory - /// problems. For example, a double-free may occur if the function is called - /// twice on the same raw pointer. - #[inline] - pub unsafe fn from_raw(ptr: *mut zend_string) -> Self { - unsafe { - Self { - inner: ZStr::from_mut_ptr(ptr), - } - } - } - - /// Consumes the ZString and transfers ownership of the string to a raw - /// pointer. - #[inline] - pub fn into_raw(mut self) -> *mut zend_string { - let ptr = self.as_mut_ptr(); - forget(self); - ptr - } -} - -impl Debug for ZString { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - common_fmt(self, f, "ZString") - } } impl Clone for ZString { @@ -246,33 +222,11 @@ impl Clone for ZString { phper_zstr_len(self.as_ptr()).try_into().unwrap(), false.into(), ); - Self { - inner: ZStr::from_mut_ptr(ptr.cast()), - } + Self::from_raw(ZStr::from_mut_ptr(ptr.cast())) } } } -impl Deref for ZString { - type Target = ZStr; - - fn deref(&self) -> &Self::Target { - unsafe { self.inner.as_ref().unwrap() } - } -} - -impl DerefMut for ZString { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { self.inner.as_mut().unwrap() } - } -} - -impl Borrow for ZString { - fn borrow(&self) -> &ZStr { - self.deref() - } -} - impl AsRef<[u8]> for ZString { fn as_ref(&self) -> &[u8] { self.to_bytes() @@ -281,15 +235,7 @@ impl AsRef<[u8]> for ZString { impl> PartialEq for ZString { fn eq(&self, other: &Rhs) -> bool { - self.as_ref() == other.as_ref() - } -} - -impl Drop for ZString { - fn drop(&mut self) { - unsafe { - phper_zend_string_release(self.as_mut_ptr()); - } + AsRef::<[u8]>::as_ref(self) == other.as_ref() } } diff --git a/phper/src/values.rs b/phper/src/values.rs index f45a14f0..d41f19ab 100644 --- a/phper/src/values.rs +++ b/phper/src/values.rs @@ -11,7 +11,6 @@ //! Apis relate to [zval]. use crate::{ - alloc::EBox, arrays::{ZArr, ZArray}, errors::ExpectTypeError, functions::{ZFunc, call_internal}, @@ -737,7 +736,7 @@ impl From for ZVal { fn from(s: ZString) -> Self { unsafe { let mut val = MaybeUninit::::uninit(); - phper_zval_str(val.as_mut_ptr().cast(), s.into_raw()); + phper_zval_str(val.as_mut_ptr().cast(), ZString::into_raw(s).cast()); val.assume_init() } } @@ -747,7 +746,7 @@ impl From for ZVal { fn from(arr: ZArray) -> Self { unsafe { let mut val = MaybeUninit::::uninit(); - phper_zval_arr(val.as_mut_ptr().cast(), arr.into_raw()); + phper_zval_arr(val.as_mut_ptr().cast(), ZArray::into_raw(arr).cast()); val.assume_init() } } @@ -757,7 +756,7 @@ impl From for ZVal { fn from(obj: ZObject) -> Self { unsafe { let mut val = MaybeUninit::::uninit(); - phper_zval_obj(val.as_mut_ptr().cast(), obj.into_raw()); + phper_zval_obj(val.as_mut_ptr().cast(), ZObject::into_raw(obj).cast()); val.assume_init() } } @@ -777,9 +776,3 @@ impl> From> for ZVal { } } } - -impl> From> for ZVal { - fn from(t: EBox) -> Self { - t.into_inner().into() - } -} diff --git a/tests/integration/src/strings.rs b/tests/integration/src/strings.rs index 2e9875e7..7ec691d7 100644 --- a/tests/integration/src/strings.rs +++ b/tests/integration/src/strings.rs @@ -18,7 +18,7 @@ pub fn integrate(module: &mut Module) { assert_eq!(zs.to_str()?, "hello"); let zs = ZString::new([1, 2, 3]); - assert_eq!(zs.as_ref(), &[1, 2, 3]); + assert_eq!(AsRef::<[u8]>::as_ref(&zs), &[1, 2, 3]); assert!(ZString::new("hello") == ZString::new(b"hello")); @@ -33,7 +33,7 @@ pub fn integrate(module: &mut Module) { assert_eq!(zs.to_str()?, "persistent_hello"); let zs = ZString::new_persistent([4, 5, 6]); - assert_eq!(zs.as_ref(), &[4, 5, 6]); + assert_eq!(AsRef::<[u8]>::as_ref(&zs), &[4, 5, 6]); assert!( ZString::new_persistent("persistent") == ZString::new_persistent(b"persistent") diff --git a/tests/integration/src/values.rs b/tests/integration/src/values.rs index c8a206e3..2f35f38e 100644 --- a/tests/integration/src/values.rs +++ b/tests/integration/src/values.rs @@ -9,7 +9,6 @@ // See the Mulan PSL v2 for more details. use phper::{ - alloc::{EBox, ebox}, arrays::{InsertKey, ZArray}, modules::Module, objects::ZObject, @@ -71,10 +70,6 @@ fn integrate_returns(module: &mut Module) { "integration_values_return_option_i64_none", integration_values_return_option_i64_none, ); - module.add_function( - "integration_values_return_ebox_i64", - integration_values_return_ebox_i64, - ); module.add_function( "integration_values_return_result_string_ok", integration_values_return_result_string_ok, @@ -146,10 +141,6 @@ fn integration_values_return_option_i64_none(_: &mut [ZVal]) -> Result Result, Infallible> { - Ok(ebox!(64)) -} - fn integration_values_return_result_string_ok( _: &mut [ZVal], ) -> phper::Result + use<>> { diff --git a/tests/integration/tests/php/values.php b/tests/integration/tests/php/values.php index 991c7721..2588b76c 100644 --- a/tests/integration/tests/php/values.php +++ b/tests/integration/tests/php/values.php @@ -25,7 +25,6 @@ assert_object(integration_values_return_object(), "stdClass", ["foo" => "bar"]); assert_eq(integration_values_return_option_i64_some(), 64); assert_eq(integration_values_return_option_i64_none(), null); -assert_eq(integration_values_return_ebox_i64(), 64); assert_eq(integration_values_return_result_string_ok(), "foo"); assert_throw("integration_values_return_result_string_err", "ErrorException", 0, "a zhe"); assert_eq(integration_values_return_val(), "foo");