@@ -24,7 +24,7 @@ use crate::{
24
24
} ;
25
25
use std:: {
26
26
any:: Any ,
27
- ffi:: { c_void, CString } ,
27
+ ffi:: { c_char , c_void, CString } ,
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,12 @@ 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 ( & mut self , name : impl Into < String > , value : impl Into < Scalar > ) {
494
+ let constant = ConstantEntity :: new ( name, value) ;
495
+ self . constants . push ( constant) ;
496
+ }
497
+
490
498
/// Register class to `extends` the parent class.
491
499
///
492
500
/// *Because in the `MINIT` phase, the class starts to register, so the*
@@ -603,6 +611,10 @@ impl<T: 'static> ClassEntity<T> {
603
611
zend_class_implements ( class_ce, 1 , interface_ce) ;
604
612
}
605
613
614
+ for constant in & self . constants {
615
+ add_class_constant ( class_ce, constant) ;
616
+ }
617
+
606
618
* phper_get_create_object ( class_ce) = Some ( create_object) ;
607
619
608
620
class_ce
@@ -680,6 +692,7 @@ unsafe extern "C" fn class_init_handler(
680
692
pub struct InterfaceEntity {
681
693
interface_name : CString ,
682
694
method_entities : Vec < MethodEntity > ,
695
+ constants : Vec < ConstantEntity > ,
683
696
extends : Vec < Box < dyn Fn ( ) -> & ' static ClassEntry > > ,
684
697
bind_interface : Option < & ' static StaticInterface > ,
685
698
}
@@ -690,6 +703,7 @@ impl InterfaceEntity {
690
703
Self {
691
704
interface_name : ensure_end_with_zero ( interface_name. into ( ) ) ,
692
705
method_entities : Vec :: new ( ) ,
706
+ constants : Vec :: new ( ) ,
693
707
extends : Vec :: new ( ) ,
694
708
bind_interface : None ,
695
709
}
@@ -704,6 +718,12 @@ impl InterfaceEntity {
704
718
self . method_entities . last_mut ( ) . unwrap ( )
705
719
}
706
720
721
+ /// Add constant to interface
722
+ pub fn add_constant ( & mut self , name : impl Into < String > , value : impl Into < Scalar > ) {
723
+ let constant = ConstantEntity :: new ( name, value) ;
724
+ self . constants . push ( constant) ;
725
+ }
726
+
707
727
/// Register interface to `extends` the interfaces, due to the interface can
708
728
/// extends multi interface, so this method can be called multi time.
709
729
///
@@ -751,6 +771,10 @@ impl InterfaceEntity {
751
771
zend_class_implements ( class_ce, 1 , interface_ce) ;
752
772
}
753
773
774
+ for constant in & self . constants {
775
+ add_class_constant ( class_ce, constant) ;
776
+ }
777
+
754
778
class_ce
755
779
}
756
780
@@ -773,6 +797,21 @@ unsafe extern "C" fn interface_init_handler(
773
797
zend_register_internal_interface ( class_ce)
774
798
}
775
799
800
+ /// Builder for registering class/interface constants
801
+ pub struct ConstantEntity {
802
+ name : String ,
803
+ value : Scalar ,
804
+ }
805
+
806
+ impl ConstantEntity {
807
+ fn new ( name : impl Into < String > , value : impl Into < Scalar > ) -> Self {
808
+ Self {
809
+ name : name. into ( ) ,
810
+ value : value. into ( ) ,
811
+ }
812
+ }
813
+ }
814
+
776
815
/// Builder for declare class property.
777
816
struct PropertyEntity {
778
817
name : String ,
@@ -973,6 +1012,47 @@ unsafe fn clone_object_common(object: *mut zend_object) -> *mut zend_object {
973
1012
new_object
974
1013
}
975
1014
1015
+ unsafe fn add_class_constant ( class_ce : * mut _zend_class_entry , constant : & ConstantEntity ) {
1016
+ let name_ptr = constant. name . as_ptr ( ) as * const c_char ;
1017
+ let name_len = constant. name . len ( ) ;
1018
+ unsafe {
1019
+ match & constant. value {
1020
+ Scalar :: Null => {
1021
+ zend_declare_class_constant_null ( class_ce, name_ptr, name_len) ;
1022
+ }
1023
+ Scalar :: Bool ( b) => {
1024
+ zend_declare_class_constant_bool ( class_ce, name_ptr, name_len, * b as zend_bool ) ;
1025
+ }
1026
+ Scalar :: I64 ( i) => {
1027
+ zend_declare_class_constant_long ( class_ce, name_ptr, name_len, * i as zend_long ) ;
1028
+ }
1029
+ Scalar :: F64 ( f) => {
1030
+ zend_declare_class_constant_double ( class_ce, name_ptr, name_len, * f) ;
1031
+ }
1032
+ Scalar :: String ( s) => {
1033
+ let s_ptr = s. as_ptr ( ) as * mut u8 ;
1034
+ zend_declare_class_constant_stringl (
1035
+ class_ce,
1036
+ name_ptr,
1037
+ name_len,
1038
+ s_ptr. cast ( ) ,
1039
+ s. len ( ) ,
1040
+ ) ;
1041
+ }
1042
+ Scalar :: Bytes ( s) => {
1043
+ let s_ptr = s. as_ptr ( ) as * mut u8 ;
1044
+ zend_declare_class_constant_stringl (
1045
+ class_ce,
1046
+ name_ptr,
1047
+ name_len,
1048
+ s_ptr. cast ( ) ,
1049
+ s. len ( ) ,
1050
+ ) ;
1051
+ }
1052
+ }
1053
+ }
1054
+ }
1055
+
976
1056
unsafe extern "C" fn free_object ( object : * mut zend_object ) {
977
1057
let state_object = StateObj :: < ( ) > :: from_mut_object_ptr ( object) ;
978
1058
0 commit comments