@@ -28,26 +28,14 @@ use std::{
28
28
ffi:: { CString , c_char, c_void} ,
29
29
fmt:: Debug ,
30
30
marker:: PhantomData ,
31
- mem:: { ManuallyDrop , replace, size_of, zeroed} ,
31
+ mem:: { ManuallyDrop , replace, size_of, transmute , zeroed} ,
32
32
os:: raw:: c_int,
33
33
ptr,
34
34
ptr:: null_mut,
35
35
rc:: Rc ,
36
36
slice,
37
37
} ;
38
38
39
- /// Predefined interface `Iterator`.
40
- #[ inline]
41
- pub fn iterator_class < ' a > ( ) -> & ' a ClassEntry {
42
- unsafe { ClassEntry :: from_ptr ( zend_ce_iterator) }
43
- }
44
-
45
- /// Predefined interface `ArrayAccess`.
46
- #[ inline]
47
- pub fn array_access_class < ' a > ( ) -> & ' a ClassEntry {
48
- unsafe { ClassEntry :: from_ptr ( zend_ce_arrayaccess) }
49
- }
50
-
51
39
/// Wrapper of [zend_class_entry].
52
40
#[ derive( Clone ) ]
53
41
#[ repr( transparent) ]
@@ -287,13 +275,26 @@ fn find_global_class_entry_ptr(name: impl AsRef<str>) -> *mut zend_class_entry {
287
275
/// ```
288
276
pub struct StateClass < T > {
289
277
inner : Rc < RefCell < * mut zend_class_entry > > ,
278
+ name : Option < String > ,
290
279
_p : PhantomData < T > ,
291
280
}
292
281
282
+ impl StateClass < ( ) > {
283
+ /// Create from name, which will be looked up from globals.
284
+ pub fn from_name ( name : impl Into < String > ) -> Self {
285
+ Self {
286
+ inner : Rc :: new ( RefCell :: new ( null_mut ( ) ) ) ,
287
+ name : Some ( name. into ( ) ) ,
288
+ _p : PhantomData ,
289
+ }
290
+ }
291
+ }
292
+
293
293
impl < T > StateClass < T > {
294
294
fn null ( ) -> Self {
295
295
Self {
296
296
inner : Rc :: new ( RefCell :: new ( null_mut ( ) ) ) ,
297
+ name : None ,
297
298
_p : PhantomData ,
298
299
}
299
300
}
@@ -304,7 +305,11 @@ impl<T> StateClass<T> {
304
305
305
306
/// Converts to class entry.
306
307
pub fn as_class_entry ( & self ) -> & ClassEntry {
307
- unsafe { ClassEntry :: from_mut_ptr ( * self . inner . borrow ( ) ) }
308
+ if let Some ( name) = & self . name {
309
+ ClassEntry :: from_globals ( name) . unwrap ( )
310
+ } else {
311
+ unsafe { ClassEntry :: from_mut_ptr ( * self . inner . borrow ( ) ) }
312
+ }
308
313
}
309
314
310
315
/// Create the object from class and call `__construct` with arguments.
@@ -333,6 +338,7 @@ impl<T> Clone for StateClass<T> {
333
338
fn clone ( & self ) -> Self {
334
339
Self {
335
340
inner : self . inner . clone ( ) ,
341
+ name : self . name . clone ( ) ,
336
342
_p : self . _p ,
337
343
}
338
344
}
@@ -427,7 +433,7 @@ pub struct ClassEntity<T: 'static> {
427
433
state_constructor : Rc < StateConstructor > ,
428
434
method_entities : Vec < MethodEntity > ,
429
435
property_entities : Vec < PropertyEntity > ,
430
- parent : Option < Box < dyn Fn ( ) -> & ' static ClassEntry > > ,
436
+ parent : Option < StateClass < ( ) > > ,
431
437
interfaces : Vec < Interface > ,
432
438
constants : Vec < ConstantEntity > ,
433
439
bind_class : StateClass < T > ,
@@ -550,19 +556,40 @@ impl<T: 'static> ClassEntity<T> {
550
556
/// Register class to `extends` the parent class.
551
557
///
552
558
/// *Because in the `MINIT` phase, the class starts to register, so the*
553
- /// *closure is used to return the `ClassEntry` to delay the acquisition of*
559
+ /// *`ClassEntry` is looked up by name to delay the acquisition of*
554
560
/// *the class.*
555
561
///
556
562
/// # Examples
557
563
///
558
564
/// ```no_run
559
- /// use phper::classes::{ClassEntity, ClassEntry};
565
+ /// use phper::{
566
+ /// classes::{ClassEntity, ClassEntry, StateClass},
567
+ /// modules::Module,
568
+ /// php_get_module,
569
+ /// };
560
570
///
561
- /// let mut class = ClassEntity::new("MyException");
562
- /// class.extends(|| ClassEntry::from_globals("Exception").unwrap());
571
+ /// #[php_get_module]
572
+ /// pub fn get_module() -> Module {
573
+ /// let mut module = Module::new(
574
+ /// env!("CARGO_CRATE_NAME"),
575
+ /// env!("CARGO_PKG_VERSION"),
576
+ /// env!("CARGO_PKG_AUTHORS"),
577
+ /// );
578
+ ///
579
+ /// let foo = module.add_class(ClassEntity::new("Foo"));
580
+ /// let mut bar = ClassEntity::new("Bar");
581
+ /// bar.extends(foo);
582
+ /// module.add_class(bar);
583
+ ///
584
+ /// let mut ex = ClassEntity::new("MyException");
585
+ /// ex.extends(StateClass::from_name("Exception"));
586
+ /// module.add_class(ex);
587
+ ///
588
+ /// module
589
+ /// }
563
590
/// ```
564
- pub fn extends ( & mut self , parent : impl Fn ( ) -> & ' static ClassEntry + ' static ) {
565
- self . parent = Some ( Box :: new ( parent) ) ;
591
+ pub fn extends < S : ' static > ( & mut self , parent : StateClass < S > ) {
592
+ self . parent = Some ( unsafe { transmute :: < StateClass < S > , StateClass < ( ) > > ( parent) } ) ;
566
593
}
567
594
568
595
/// Register class to `implements` the interface, due to the class can
@@ -634,7 +661,7 @@ impl<T: 'static> ClassEntity<T> {
634
661
let parent: * mut zend_class_entry = self
635
662
. parent
636
663
. as_ref ( )
637
- . map ( |parent| parent ( ) )
664
+ . map ( |parent| parent. as_class_entry ( ) )
638
665
. map ( |entry| entry. as_ptr ( ) as * mut _ )
639
666
. unwrap_or ( null_mut ( ) ) ;
640
667
@@ -800,20 +827,24 @@ impl InterfaceEntity {
800
827
/// Register interface to `extends` the interfaces, due to the interface can
801
828
/// extends multi interface, so this method can be called multi time.
802
829
///
803
- /// *Because in the `MINIT` phase, the class starts to register, so the *
830
+ /// *Because in the `MINIT` phase, the class starts to register, a *
804
831
/// *closure is used to return the `ClassEntry` to delay the acquisition of*
805
832
/// *the class.*
806
833
///
807
834
/// # Examples
808
835
///
809
836
/// ```no_run
810
- /// use phper::classes::{ClassEntry , InterfaceEntity};
837
+ /// use phper::classes::{Interface , InterfaceEntity};
811
838
///
812
839
/// let mut interface = InterfaceEntity::new("MyInterface");
813
- /// interface.extends(|| ClassEntry::from_globals ("Stringable").unwrap( ));
840
+ /// interface.extends(Interface::from_name ("Stringable"));
814
841
/// ```
815
- pub fn extends ( & mut self , interface : impl Fn ( ) -> & ' static ClassEntry + ' static ) {
816
- self . extends . push ( Box :: new ( interface) ) ;
842
+ pub fn extends ( & mut self , interface : Interface ) {
843
+ self . extends . push ( Box :: new ( move || {
844
+ let entry: & ' static ClassEntry =
845
+ unsafe { std:: mem:: transmute ( interface. as_class_entry ( ) ) } ;
846
+ entry
847
+ } ) ) ;
817
848
}
818
849
819
850
#[ allow( clippy:: useless_conversion) ]
0 commit comments