1010
1111//! Apis relate to [crate::sys::zend_ini_entry_def].
1212
13- use crate :: sys:: {
14- phper_zend_ini_mh, zend_ini_entry_def, OnUpdateBool , OnUpdateLong , OnUpdateReal ,
15- OnUpdateString , PHP_INI_ALL , PHP_INI_PERDIR , PHP_INI_SYSTEM , PHP_INI_USER ,
16- } ;
17- use dashmap:: DashMap ;
13+ use crate :: sys:: * ;
1814use std:: {
19- any:: TypeId ,
2015 ffi:: CStr ,
21- mem:: { size_of , zeroed } ,
22- os:: raw:: { c_char, c_void } ,
16+ mem:: { zeroed , ManuallyDrop } ,
17+ os:: raw:: c_char,
2318 ptr:: null_mut,
2419 str,
25- sync:: atomic:: { AtomicBool , Ordering } ,
2620} ;
2721
28- static REGISTERED : AtomicBool = AtomicBool :: new ( false ) ;
29-
30- thread_local ! {
31- static INI_ENTITIES : DashMap <String , IniEntity > = DashMap :: new( ) ;
22+ pub fn ini_get < T : FromIniValue > ( name : & str ) -> T {
23+ T :: from_ini_value ( name)
3224}
3325
34- pub struct Ini ;
35-
36- impl Ini {
37- pub fn add ( name : impl Into < String > , default_value : impl TransformIniValue , policy : Policy ) {
38- assert ! (
39- !REGISTERED . load( Ordering :: SeqCst ) ,
40- "shouldn't add ini after registered"
41- ) ;
42-
43- let name = name. into ( ) ;
44-
45- INI_ENTITIES . with ( |ini_entities| {
46- ini_entities. insert ( name. clone ( ) , IniEntity :: new ( name, default_value, policy) ) ;
47- } ) ;
48- }
49-
50- pub fn get < T : TransformIniValue > ( name : & str ) -> Option < T > {
51- assert ! (
52- REGISTERED . load( Ordering :: SeqCst ) ,
53- "shouldn't get ini before registered"
54- ) ;
55-
56- INI_ENTITIES . with ( |ini_entities| {
57- ini_entities
58- . get ( name)
59- . and_then ( |entity| entity. value ( ) . value ( ) )
60- } )
61- }
62-
63- pub ( crate ) unsafe fn entries ( ) -> * const zend_ini_entry_def {
64- REGISTERED . store ( true , Ordering :: SeqCst ) ;
65-
66- let mut entries = Vec :: new ( ) ;
67-
68- INI_ENTITIES . with ( |ini_entities| {
69- for mut entity in ini_entities. iter_mut ( ) {
70- entries. push ( entity. value_mut ( ) . entry ( ) ) ;
71- }
72- } ) ;
73-
74- entries. push ( zeroed :: < zend_ini_entry_def > ( ) ) ;
75-
76- Box :: into_raw ( entries. into_boxed_slice ( ) ) . cast ( )
77- }
78- }
79-
80- pub type OnModify = phper_zend_ini_mh ;
81-
8226#[ repr( u32 ) ]
8327#[ derive( Copy , Clone ) ]
8428pub enum Policy {
@@ -89,145 +33,109 @@ pub enum Policy {
8933}
9034
9135/// The Type which can transform to an ini value.
92- ///
93- /// Be careful that the size of `arg2` must litter than size of `usize`.
94- ///
95- /// TODO Add a size compare with usize trait bound, after const generic
96- /// supports.
97- pub trait TransformIniValue : Sized + ToString + ' static {
98- fn on_modify ( ) -> OnModify ;
99-
100- /// # Safety
101- unsafe fn transform ( data : usize ) -> Option < Self > ;
102-
103- fn arg2_type ( ) -> TypeId ;
104-
105- fn arg2_size ( ) -> usize ;
106-
107- fn to_text ( & self ) -> String {
108- self . to_string ( )
109- }
36+ pub trait IntoIniValue {
37+ fn into_ini_value ( self ) -> String ;
11038}
11139
112- impl TransformIniValue for bool {
113- fn on_modify ( ) -> OnModify {
114- Some ( OnUpdateBool )
115- }
116-
117- unsafe fn transform ( data : usize ) -> Option < Self > {
118- Some ( data != 0 )
119- }
120-
121- fn arg2_type ( ) -> TypeId {
122- TypeId :: of :: < bool > ( )
123- }
124-
125- fn arg2_size ( ) -> usize {
126- size_of :: < bool > ( )
40+ impl IntoIniValue for bool {
41+ #[ inline]
42+ fn into_ini_value ( self ) -> String {
43+ if self {
44+ "1" . to_owned ( )
45+ } else {
46+ "0" . to_owned ( )
47+ }
12748 }
12849}
12950
130- impl TransformIniValue for i64 {
131- fn on_modify ( ) -> OnModify {
132- Some ( OnUpdateLong )
133- }
134-
135- unsafe fn transform ( data : usize ) -> Option < Self > {
136- Some ( data as i64 )
137- }
138-
139- fn arg2_type ( ) -> TypeId {
140- TypeId :: of :: < i64 > ( )
141- }
142-
143- fn arg2_size ( ) -> usize {
144- size_of :: < i64 > ( )
51+ impl IntoIniValue for i64 {
52+ #[ inline]
53+ fn into_ini_value ( self ) -> String {
54+ self . to_string ( )
14555 }
14656}
14757
148- impl TransformIniValue for f64 {
149- fn on_modify ( ) -> OnModify {
150- Some ( OnUpdateReal )
151- }
152-
153- unsafe fn transform ( data : usize ) -> Option < Self > {
154- Some ( data as f64 )
58+ impl IntoIniValue for f64 {
59+ #[ inline]
60+ fn into_ini_value ( self ) -> String {
61+ self . to_string ( )
15562 }
63+ }
15664
157- fn arg2_type ( ) -> TypeId {
158- TypeId :: of :: < i64 > ( )
65+ impl IntoIniValue for String {
66+ #[ inline]
67+ fn into_ini_value ( self ) -> String {
68+ self
15969 }
70+ }
16071
161- fn arg2_size ( ) -> usize {
162- size_of :: < i64 > ( )
163- }
72+ /// For php7, the zend_ini_* functions receive ini name as `*mut c_char`, but I
73+ /// think it's immutable.
74+ pub trait FromIniValue {
75+ fn from_ini_value ( name : & str ) -> Self ;
16476}
16577
166- impl TransformIniValue for String {
167- fn on_modify ( ) -> OnModify {
168- Some ( OnUpdateString )
78+ impl FromIniValue for bool {
79+ fn from_ini_value ( name : & str ) -> Self {
80+ unsafe {
81+ let name_ptr = name. as_ptr ( ) as * mut u8 as * mut c_char ;
82+ zend_ini_long ( name_ptr, name. len ( ) . try_into ( ) . unwrap ( ) , 0 ) != 0
83+ }
16984 }
85+ }
17086
171- unsafe fn transform ( data : usize ) -> Option < Self > {
172- let ptr = data as * mut c_char ;
173- CStr :: from_ptr ( ptr) . to_str ( ) . ok ( ) . map ( |s| s. to_owned ( ) )
87+ impl FromIniValue for i64 {
88+ fn from_ini_value ( name : & str ) -> Self {
89+ unsafe {
90+ let name_ptr = name. as_ptr ( ) as * mut u8 as * mut c_char ;
91+ zend_ini_long ( name_ptr, name. len ( ) . try_into ( ) . unwrap ( ) , 0 )
92+ }
17493 }
94+ }
17595
176- fn arg2_type ( ) -> TypeId {
177- TypeId :: of :: < * mut c_char > ( )
96+ impl FromIniValue for f64 {
97+ fn from_ini_value ( name : & str ) -> Self {
98+ unsafe {
99+ let name_ptr = name. as_ptr ( ) as * mut u8 as * mut c_char ;
100+ zend_ini_double ( name_ptr, name. len ( ) . try_into ( ) . unwrap ( ) , 0 )
101+ }
178102 }
103+ }
179104
180- fn arg2_size ( ) -> usize {
181- size_of :: < * mut c_char > ( )
105+ impl FromIniValue for Option < & CStr > {
106+ fn from_ini_value ( name : & str ) -> Self {
107+ unsafe {
108+ let name_ptr = name. as_ptr ( ) as * mut u8 as * mut c_char ;
109+ let ptr = zend_ini_string_ex ( name_ptr, name. len ( ) . try_into ( ) . unwrap ( ) , 0 , null_mut ( ) ) ;
110+ ( !ptr. is_null ( ) ) . then ( || CStr :: from_ptr ( ptr) )
111+ }
182112 }
183113}
184114
185115pub ( crate ) struct IniEntity {
186116 name : String ,
187- value : usize ,
188- value_type_id : TypeId ,
189117 default_value : String ,
190- on_modify : OnModify ,
191118 policy : Policy ,
192119}
193120
194121impl IniEntity {
195- pub ( crate ) fn new < T : TransformIniValue > (
122+ pub ( crate ) fn new < T : IntoIniValue > (
196123 name : impl Into < String > , default_value : T , policy : Policy ,
197124 ) -> Self {
198- assert ! ( <T >:: arg2_size( ) <= size_of:: <usize >( ) ) ;
199125 Self {
200126 name : name. into ( ) ,
201- value : 0 ,
202- value_type_id : <T >:: arg2_type ( ) ,
203- default_value : default_value. to_text ( ) ,
204- on_modify : <T >:: on_modify ( ) ,
127+ default_value : default_value. into_ini_value ( ) ,
205128 policy,
206129 }
207130 }
208131
209- pub ( crate ) fn value < T : TransformIniValue > ( & self ) -> Option < T > {
210- if self . value_type_id != <T >:: arg2_type ( ) {
211- None
212- } else {
213- unsafe { <T >:: transform ( self . value ) }
214- }
215- }
216-
132+ #[ inline]
217133 pub ( crate ) fn entry ( & mut self ) -> zend_ini_entry_def {
218- create_ini_entry_ex (
219- & self . name ,
220- & self . default_value ,
221- self . on_modify ,
222- self . policy as u32 ,
223- & mut self . value as * mut _ as * mut c_void ,
224- )
134+ create_ini_entry_ex ( & self . name , & self . default_value , self . policy as u32 )
225135 }
226136}
227137
228- pub ( crate ) fn create_ini_entry_ex (
229- name : & str , default_value : & str , on_modify : OnModify , modifiable : u32 , arg2 : * mut c_void ,
230- ) -> zend_ini_entry_def {
138+ fn create_ini_entry_ex ( name : & str , default_value : & str , modifiable : u32 ) -> zend_ini_entry_def {
231139 #[ cfg( any(
232140 phper_php_version = "8.1" ,
233141 phper_php_version = "8.0" ,
@@ -244,9 +152,9 @@ pub(crate) fn create_ini_entry_ex(
244152
245153 zend_ini_entry_def {
246154 name : name. as_ptr ( ) . cast ( ) ,
247- on_modify,
155+ on_modify : None ,
248156 mh_arg1 : null_mut ( ) ,
249- mh_arg2 : arg2 ,
157+ mh_arg2 : null_mut ( ) ,
250158 mh_arg3 : null_mut ( ) ,
251159 value : default_value. as_ptr ( ) . cast ( ) ,
252160 displayer : None ,
@@ -255,3 +163,17 @@ pub(crate) fn create_ini_entry_ex(
255163 value_length : default_value. len ( ) as u32 ,
256164 }
257165}
166+
167+ pub ( crate ) unsafe fn entries ( ini_entries : Vec < IniEntity > ) -> * const zend_ini_entry_def {
168+ let mut entries = Vec :: with_capacity ( ini_entries. len ( ) + 1 ) ;
169+
170+ ini_entries. into_iter ( ) . for_each ( |entity| {
171+ // Ini entity will exist throughout the whole application life cycle.
172+ let mut entity = ManuallyDrop :: new ( entity) ;
173+ entries. push ( entity. entry ( ) ) ;
174+ } ) ;
175+
176+ entries. push ( zeroed :: < zend_ini_entry_def > ( ) ) ;
177+
178+ Box :: into_raw ( entries. into_boxed_slice ( ) ) . cast ( )
179+ }
0 commit comments