@@ -24,7 +24,7 @@ use crate::{
24
24
} ;
25
25
use std:: {
26
26
any:: Any ,
27
- ffi:: { c_void, CString } ,
27
+ ffi:: { c_void, CString , c_char } ,
28
28
fmt:: Debug ,
29
29
marker:: PhantomData ,
30
30
mem:: { replace, size_of, zeroed, ManuallyDrop } ,
@@ -377,6 +377,7 @@ pub struct ClassEntity<T: 'static> {
377
377
property_entities : Vec < PropertyEntity > ,
378
378
parent : Option < Box < dyn Fn ( ) -> & ' static ClassEntry > > ,
379
379
interfaces : Vec < Box < dyn Fn ( ) -> & ' static ClassEntry > > ,
380
+ constants : Vec < ConstantEntity > ,
380
381
bind_class : Option < & ' static StaticStateClass < T > > ,
381
382
state_cloner : Option < Rc < StateCloner > > ,
382
383
_p : PhantomData < ( * mut ( ) , T ) > ,
@@ -414,6 +415,7 @@ impl<T: 'static> ClassEntity<T> {
414
415
property_entities : Vec :: new ( ) ,
415
416
parent : None ,
416
417
interfaces : Vec :: new ( ) ,
418
+ constants : Vec :: new ( ) ,
417
419
bind_class : None ,
418
420
state_cloner : None ,
419
421
_p : PhantomData ,
@@ -487,6 +489,13 @@ impl<T: 'static> ClassEntity<T> {
487
489
self . property_entities . push ( entity) ;
488
490
}
489
491
492
+ /// Add constant to class
493
+ pub fn add_constant (
494
+ & mut self , name : impl Into < String > , value : impl Into < Scalar > ) {
495
+ let constant = ConstantEntity :: new ( name, value) ;
496
+ self . constants . push ( constant) ;
497
+ }
498
+
490
499
/// Register class to `extends` the parent class.
491
500
///
492
501
/// *Because in the `MINIT` phase, the class starts to register, so the*
@@ -603,6 +612,10 @@ impl<T: 'static> ClassEntity<T> {
603
612
zend_class_implements ( class_ce, 1 , interface_ce) ;
604
613
}
605
614
615
+ for constant in & self . constants {
616
+ add_class_constant ( class_ce, constant) ;
617
+ }
618
+
606
619
* phper_get_create_object ( class_ce) = Some ( create_object) ;
607
620
608
621
class_ce
@@ -680,6 +693,7 @@ unsafe extern "C" fn class_init_handler(
680
693
pub struct InterfaceEntity {
681
694
interface_name : CString ,
682
695
method_entities : Vec < MethodEntity > ,
696
+ constants : Vec < ConstantEntity > ,
683
697
extends : Vec < Box < dyn Fn ( ) -> & ' static ClassEntry > > ,
684
698
bind_interface : Option < & ' static StaticInterface > ,
685
699
}
@@ -690,6 +704,7 @@ impl InterfaceEntity {
690
704
Self {
691
705
interface_name : ensure_end_with_zero ( interface_name. into ( ) ) ,
692
706
method_entities : Vec :: new ( ) ,
707
+ constants : Vec :: new ( ) ,
693
708
extends : Vec :: new ( ) ,
694
709
bind_interface : None ,
695
710
}
@@ -704,6 +719,13 @@ impl InterfaceEntity {
704
719
self . method_entities . last_mut ( ) . unwrap ( )
705
720
}
706
721
722
+ /// Add constant to interface
723
+ pub fn add_constant (
724
+ & mut self , name : impl Into < String > , value : impl Into < Scalar > ) {
725
+ let constant = ConstantEntity :: new ( name, value) ;
726
+ self . constants . push ( constant) ;
727
+ }
728
+
707
729
/// Register interface to `extends` the interfaces, due to the interface can
708
730
/// extends multi interface, so this method can be called multi time.
709
731
///
@@ -751,6 +773,10 @@ impl InterfaceEntity {
751
773
zend_class_implements ( class_ce, 1 , interface_ce) ;
752
774
}
753
775
776
+ for constant in & self . constants {
777
+ add_class_constant ( class_ce, constant) ;
778
+ }
779
+
754
780
class_ce
755
781
}
756
782
@@ -773,6 +799,21 @@ unsafe extern "C" fn interface_init_handler(
773
799
zend_register_internal_interface ( class_ce)
774
800
}
775
801
802
+ /// Builder for registering class/interface constants
803
+ pub struct ConstantEntity {
804
+ name : String ,
805
+ value : Scalar ,
806
+ }
807
+
808
+ impl ConstantEntity {
809
+ fn new ( name : impl Into < String > , value : impl Into < Scalar > ) -> Self {
810
+ Self {
811
+ name : name. into ( ) ,
812
+ value : value. into ( ) ,
813
+ }
814
+ }
815
+ }
816
+
776
817
/// Builder for declare class property.
777
818
struct PropertyEntity {
778
819
name : String ,
@@ -973,6 +1014,54 @@ unsafe fn clone_object_common(object: *mut zend_object) -> *mut zend_object {
973
1014
new_object
974
1015
}
975
1016
1017
+ unsafe fn add_class_constant ( class_ce : * mut _zend_class_entry , constant : & ConstantEntity ) {
1018
+ let name_ptr = constant. name . as_ptr ( ) as * const c_char ;
1019
+ let name_len = constant. name . len ( ) ;
1020
+ unsafe {
1021
+ match & constant. value {
1022
+ Scalar :: Null => zend_declare_class_constant_null ( class_ce, name_ptr, name_len) ,
1023
+ Scalar :: Bool ( b) => zend_declare_class_constant_bool (
1024
+ class_ce,
1025
+ name_ptr,
1026
+ name_len,
1027
+ * b as zend_bool ,
1028
+ ) ,
1029
+ Scalar :: I64 ( i) => zend_declare_class_constant_long (
1030
+ class_ce,
1031
+ name_ptr,
1032
+ name_len,
1033
+ * i as zend_long ,
1034
+ ) ,
1035
+ Scalar :: F64 ( f) => zend_declare_class_constant_double (
1036
+ class_ce,
1037
+ name_ptr,
1038
+ name_len,
1039
+ * f
1040
+ ) ,
1041
+ Scalar :: String ( s) => {
1042
+ let s_ptr = s. as_ptr ( ) as * mut u8 ;
1043
+ zend_declare_class_constant_stringl (
1044
+ class_ce,
1045
+ name_ptr,
1046
+ name_len,
1047
+ s_ptr. cast ( ) ,
1048
+ s. len ( ) ,
1049
+ )
1050
+ }
1051
+ Scalar :: Bytes ( s) => {
1052
+ let s_ptr = s. as_ptr ( ) as * mut u8 ;
1053
+ zend_declare_class_constant_stringl (
1054
+ class_ce,
1055
+ name_ptr,
1056
+ name_len,
1057
+ s_ptr. cast ( ) ,
1058
+ s. len ( ) ,
1059
+ )
1060
+ }
1061
+ }
1062
+ }
1063
+ }
1064
+
976
1065
unsafe extern "C" fn free_object ( object : * mut zend_object ) {
977
1066
let state_object = StateObj :: < ( ) > :: from_mut_object_ptr ( object) ;
978
1067
0 commit comments