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

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions