Skip to content

(feature) Consumption of Zvals #526

@kakserpom

Description

@kakserpom

Status quo

Now in a function/method definition it is either &Zval or &mut Zval:

#[php_function]
pub fn foo(arg: &Zval) {}
#[php_function]
pub fn foo_mut(arg: &mut Zval) {}

#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
    module
        .function(wrap_function!(foo))
        .function(wrap_function!(foo_mut))
}
foo([1,2,3]); // this one is fine
foo_mut([1,2,3]); //  Error: foo_mut(): Argument #1 ($arg) could not be passed by reference

So currently I am always using &Zval and just cloning the values.

Solution?

Introduce methods like this into types::zval (they should take immutable refs):

/// Returns a mutable reference to the underlying zval hashtable if the zval
/// contains an array.
pub fn array_mut_forced(&self) -> Option<&mut ZendHashTable> {
    if self.is_array() {
        unsafe { self.value.arr.as_mut() }
    } else {
        None
    }
}

But then mem::take() doesn't work, because Default is not implemented.


By the way, regarding types::array, currently into_iter() doesn't consume, so it's kind of misleading:

types/array.rs:

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        Iter::new(self)
    }
...
impl<'a> Iter<'a> {
    /// Creates a new iterator over a hashtable.
    ///
    /// # Parameters
    ///
    /// * `ht` - The hashtable to iterate.
    pub fn new(ht: &'a ZendHashTable) -> Self {
     ...
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions