Merge branch 'zval_shallow_clone'

This commit is contained in:
David Cole 2022-02-22 11:14:34 +13:00
commit a09b8474bb
2 changed files with 33 additions and 1 deletions

View File

@ -101,7 +101,7 @@ fn main() {
.clang_args(includes.split(' '))
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.rustfmt_bindings(true)
.no_copy("_zend_value")
.no_copy("_zval_struct")
.no_copy("_zend_string")
.no_copy("_zend_array")
.layout_tests(env::var("EXT_PHP_RS_TEST").is_ok());

View File

@ -500,6 +500,38 @@ impl Zval {
{
FromZval::from_zval(self)
}
/// Creates a shallow clone of the [`Zval`].
///
/// This copies the contents of the [`Zval`], and increments the reference
/// counter of the underlying value (if it is reference counted).
///
/// For example, if the zval contains a long, it will simply copy the value.
/// However, if the zval contains an object, the new zval will point to the
/// same object, and the objects reference counter will be incremented.
///
/// # Returns
///
/// The cloned zval.
pub fn shallow_clone(&self) -> Zval {
let mut new = Zval::new();
new.u1 = self.u1;
new.value = self.value;
// SAFETY: `u1` union is only used for easier bitmasking. It is valid to read
// from either of the variants.
//
// SAFETY: If the value if refcounted (`self.u1.type_info & Z_TYPE_FLAGS_MASK`)
// then it is valid to dereference `self.value.counted`.
unsafe {
let flags = ZvalTypeFlags::from_bits_unchecked(self.u1.type_info);
if flags.contains(ZvalTypeFlags::RefCounted) {
(*self.value.counted).gc.refcount += 1;
}
}
new
}
}
impl Debug for Zval {