Skip to content

Commit

Permalink
Add shallow_clone to Zval
Browse files Browse the repository at this point in the history
  • Loading branch information
davidcole1340 committed Dec 13, 2021
1 parent 705be68 commit f9528f0
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
32 changes: 32 additions & 0 deletions src/types/zval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit f9528f0

Please sign in to comment.