@@ -24,7 +24,7 @@ use crate::{
2424} ;
2525use std:: {
2626 any:: Any ,
27- ffi:: { c_void, CString } ,
27+ ffi:: { c_void, CString , c_char } ,
2828 fmt:: Debug ,
2929 marker:: PhantomData ,
3030 mem:: { replace, size_of, zeroed, ManuallyDrop } ,
@@ -377,6 +377,7 @@ pub struct ClassEntity<T: 'static> {
377377 property_entities : Vec < PropertyEntity > ,
378378 parent : Option < Box < dyn Fn ( ) -> & ' static ClassEntry > > ,
379379 interfaces : Vec < Box < dyn Fn ( ) -> & ' static ClassEntry > > ,
380+ constants : Vec < ConstantEntity > ,
380381 bind_class : Option < & ' static StaticStateClass < T > > ,
381382 state_cloner : Option < Rc < StateCloner > > ,
382383 _p : PhantomData < ( * mut ( ) , T ) > ,
@@ -414,6 +415,7 @@ impl<T: 'static> ClassEntity<T> {
414415 property_entities : Vec :: new ( ) ,
415416 parent : None ,
416417 interfaces : Vec :: new ( ) ,
418+ constants : Vec :: new ( ) ,
417419 bind_class : None ,
418420 state_cloner : None ,
419421 _p : PhantomData ,
@@ -487,6 +489,13 @@ impl<T: 'static> ClassEntity<T> {
487489 self . property_entities . push ( entity) ;
488490 }
489491
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+
490499 /// Register class to `extends` the parent class.
491500 ///
492501 /// *Because in the `MINIT` phase, the class starts to register, so the*
@@ -603,6 +612,10 @@ impl<T: 'static> ClassEntity<T> {
603612 zend_class_implements ( class_ce, 1 , interface_ce) ;
604613 }
605614
615+ for constant in & self . constants {
616+ add_class_constant ( class_ce, constant) ;
617+ }
618+
606619 * phper_get_create_object ( class_ce) = Some ( create_object) ;
607620
608621 class_ce
@@ -680,6 +693,7 @@ unsafe extern "C" fn class_init_handler(
680693pub struct InterfaceEntity {
681694 interface_name : CString ,
682695 method_entities : Vec < MethodEntity > ,
696+ constants : Vec < ConstantEntity > ,
683697 extends : Vec < Box < dyn Fn ( ) -> & ' static ClassEntry > > ,
684698 bind_interface : Option < & ' static StaticInterface > ,
685699}
@@ -690,6 +704,7 @@ impl InterfaceEntity {
690704 Self {
691705 interface_name : ensure_end_with_zero ( interface_name. into ( ) ) ,
692706 method_entities : Vec :: new ( ) ,
707+ constants : Vec :: new ( ) ,
693708 extends : Vec :: new ( ) ,
694709 bind_interface : None ,
695710 }
@@ -704,6 +719,13 @@ impl InterfaceEntity {
704719 self . method_entities . last_mut ( ) . unwrap ( )
705720 }
706721
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+
707729 /// Register interface to `extends` the interfaces, due to the interface can
708730 /// extends multi interface, so this method can be called multi time.
709731 ///
@@ -751,6 +773,10 @@ impl InterfaceEntity {
751773 zend_class_implements ( class_ce, 1 , interface_ce) ;
752774 }
753775
776+ for constant in & self . constants {
777+ add_class_constant ( class_ce, constant) ;
778+ }
779+
754780 class_ce
755781 }
756782
@@ -773,6 +799,21 @@ unsafe extern "C" fn interface_init_handler(
773799 zend_register_internal_interface ( class_ce)
774800}
775801
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+
776817/// Builder for declare class property.
777818struct PropertyEntity {
778819 name : String ,
@@ -973,6 +1014,54 @@ unsafe fn clone_object_common(object: *mut zend_object) -> *mut zend_object {
9731014 new_object
9741015}
9751016
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+
9761065unsafe extern "C" fn free_object ( object : * mut zend_object ) {
9771066 let state_object = StateObj :: < ( ) > :: from_mut_object_ptr ( object) ;
9781067
0 commit comments