@@ -112,9 +112,7 @@ macro_rules! call_user_func {
112112#[ macro_export]
113113macro_rules! parse_args {
114114 ( $ed: expr, $( $arg: expr) ,* ) => { {
115- use $crate:: php:: args:: ArgParser ;
116-
117- let parser = ArgParser :: new( $ed)
115+ let parser = $ed. parser( )
118116 $( . arg( & mut $arg) ) *
119117 . parse( ) ;
120118 if parser. is_err( ) {
@@ -125,7 +123,7 @@ macro_rules! parse_args {
125123 ( $ed: expr, $( $arg: expr) ,* ; $( $opt: expr) ,* ) => { {
126124 use $crate:: php:: args:: ArgParser ;
127125
128- let parser = ArgParser :: new ( $ed)
126+ let parser = $ed. parser ( )
129127 $( . arg( & mut $arg) ) *
130128 . not_required( )
131129 $( . arg( & mut $opt) ) *
@@ -163,3 +161,147 @@ macro_rules! throw {
163161 return ;
164162 } ;
165163}
164+
165+ /// Implements a set of traits required to convert types that implement [`RegisteredClass`] to and
166+ /// from [`ZendObject`]s and [`Zval`]s. Generally, this macro should not be called directly, as it
167+ /// is called on any type that uses the [`#[php_class]`] macro.
168+ ///
169+ /// The following traits are implemented:
170+ ///
171+ /// * `FromZendObject for &'a T`
172+ /// * `FromZendObjectMut for &'a mut T`
173+ /// * `FromZval for &'a T`
174+ /// * `FromZvalMut for &'a mut T`
175+ /// * `IntoZendObject for T`
176+ /// * `IntoZval for T`
177+ ///
178+ /// These implementations are required while we wait on the stabilisation of specialisation.
179+ ///
180+ /// # Examples
181+ ///
182+ /// ```
183+ /// # use ext_php_rs::{php::types::{zval::{Zval, IntoZval, FromZval}, object::{ZendObject, RegisteredClass}}};
184+ /// use ext_php_rs::class_derives;
185+ ///
186+ /// struct Test {
187+ /// a: i32,
188+ /// b: i64
189+ /// }
190+ ///
191+ /// impl RegisteredClass for Test {
192+ /// const CLASS_NAME: &'static str = "Test";
193+ ///
194+ /// const CONSTRUCTOR: Option<ext_php_rs::php::types::object::ConstructorMeta<Self>> = None;
195+ ///
196+ /// fn get_metadata() -> &'static ext_php_rs::php::types::object::ClassMetadata<Self> {
197+ /// todo!()
198+ /// }
199+ ///
200+ /// fn get_properties<'a>(
201+ /// ) -> std::collections::HashMap<&'static str, ext_php_rs::php::types::props::Property<'a, Self>>
202+ /// {
203+ /// todo!()
204+ /// }
205+ /// }
206+ ///
207+ /// class_derives!(Test);
208+ ///
209+ /// fn into_zval_test() -> Zval {
210+ /// let x = Test { a: 5, b: 10 };
211+ /// x.into_zval(false).unwrap()
212+ /// }
213+ ///
214+ /// fn from_zval_test<'a>(zv: &'a Zval) -> &'a Test {
215+ /// <&Test>::from_zval(zv).unwrap()
216+ /// }
217+ /// ```
218+ ///
219+ /// [`RegisteredClass`]: crate::php::types::object::RegisteredClass
220+ /// [`ZendObject`]: crate::php::types::object::ZendObject
221+ /// [`Zval`]: crate::php::types::zval::Zval
222+ /// [`#[php_class]`]: crate::php_class
223+ #[ macro_export]
224+ macro_rules! class_derives {
225+ ( $type: ty) => {
226+ impl <' a> $crate:: php:: types:: object:: FromZendObject <' a> for & ' a $type {
227+ #[ inline]
228+ fn from_zend_object(
229+ obj: & ' a $crate:: php:: types:: object:: ZendObject ,
230+ ) -> $crate:: errors:: Result <Self > {
231+ let obj = $crate:: php:: types:: object:: ZendClassObject :: <$type>:: from_zend_obj( obj)
232+ . ok_or( $crate:: errors:: Error :: InvalidScope ) ?;
233+ Ok ( & * * obj)
234+ }
235+ }
236+
237+ impl <' a> $crate:: php:: types:: object:: FromZendObjectMut <' a> for & ' a mut $type {
238+ #[ inline]
239+ fn from_zend_object_mut(
240+ obj: & ' a mut $crate:: php:: types:: object:: ZendObject ,
241+ ) -> $crate:: errors:: Result <Self > {
242+ let obj =
243+ $crate:: php:: types:: object:: ZendClassObject :: <$type>:: from_zend_obj_mut( obj)
244+ . ok_or( $crate:: errors:: Error :: InvalidScope ) ?;
245+ Ok ( & mut * * obj)
246+ }
247+ }
248+
249+ impl <' a> $crate:: php:: types:: zval:: FromZval <' a> for & ' a $type {
250+ const TYPE : $crate:: php:: enums:: DataType = $crate:: php:: enums:: DataType :: Object ( Some (
251+ <$type as $crate:: php:: types:: object:: RegisteredClass >:: CLASS_NAME ,
252+ ) ) ;
253+
254+ #[ inline]
255+ fn from_zval( zval: & ' a $crate:: php:: types:: zval:: Zval ) -> :: std:: option:: Option <Self > {
256+ <Self as $crate:: php:: types:: object:: FromZendObject >:: from_zend_object(
257+ zval. object( ) ?,
258+ )
259+ . ok( )
260+ }
261+ }
262+
263+ impl <' a> $crate:: php:: types:: zval:: FromZvalMut <' a> for & ' a mut $type {
264+ const TYPE : $crate:: php:: enums:: DataType = $crate:: php:: enums:: DataType :: Object ( Some (
265+ <$type as $crate:: php:: types:: object:: RegisteredClass >:: CLASS_NAME ,
266+ ) ) ;
267+
268+ #[ inline]
269+ fn from_zval_mut(
270+ zval: & ' a mut $crate:: php:: types:: zval:: Zval ,
271+ ) -> :: std:: option:: Option <Self > {
272+ <Self as $crate:: php:: types:: object:: FromZendObjectMut >:: from_zend_object_mut(
273+ zval. object_mut( ) ?,
274+ )
275+ . ok( )
276+ }
277+ }
278+
279+ impl $crate:: php:: types:: object:: IntoZendObject for $type {
280+ #[ inline]
281+ fn into_zend_object(
282+ self ,
283+ ) -> $crate:: errors:: Result <
284+ $crate:: php:: boxed:: ZBox <$crate:: php:: types:: object:: ZendObject >,
285+ > {
286+ Ok ( $crate:: php:: types:: object:: ZendClassObject :: new( self ) . into( ) )
287+ }
288+ }
289+
290+ impl $crate:: php:: types:: zval:: IntoZval for $type {
291+ const TYPE : $crate:: php:: enums:: DataType = $crate:: php:: enums:: DataType :: Object ( Some (
292+ <$type as $crate:: php:: types:: object:: RegisteredClass >:: CLASS_NAME ,
293+ ) ) ;
294+
295+ #[ inline]
296+ fn set_zval(
297+ self ,
298+ zv: & mut $crate:: php:: types:: zval:: Zval ,
299+ persistent: bool ,
300+ ) -> $crate:: errors:: Result <( ) > {
301+ use $crate:: php:: types:: object:: IntoZendObject ;
302+
303+ self . into_zend_object( ) ?. set_zval( zv, persistent)
304+ }
305+ }
306+ } ;
307+ }
0 commit comments