10
10
11
11
//! Apis relate to [crate::sys::zend_ini_entry_def].
12
12
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:: * ;
18
14
use std:: {
19
- any:: TypeId ,
20
15
ffi:: CStr ,
21
- mem:: { size_of , zeroed } ,
22
- os:: raw:: { c_char, c_void } ,
16
+ mem:: { zeroed , ManuallyDrop } ,
17
+ os:: raw:: c_char,
23
18
ptr:: null_mut,
24
19
str,
25
- sync:: atomic:: { AtomicBool , Ordering } ,
26
20
} ;
27
21
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)
32
24
}
33
25
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
-
82
26
#[ repr( u32 ) ]
83
27
#[ derive( Copy , Clone ) ]
84
28
pub enum Policy {
@@ -89,145 +33,109 @@ pub enum Policy {
89
33
}
90
34
91
35
/// 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 ;
110
38
}
111
39
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
+ }
127
48
}
128
49
}
129
50
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 ( )
145
55
}
146
56
}
147
57
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 ( )
155
62
}
63
+ }
156
64
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
159
69
}
70
+ }
160
71
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 ;
164
76
}
165
77
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
+ }
169
84
}
85
+ }
170
86
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
+ }
174
93
}
94
+ }
175
95
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
+ }
178
102
}
103
+ }
179
104
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
+ }
182
112
}
183
113
}
184
114
185
115
pub ( crate ) struct IniEntity {
186
116
name : String ,
187
- value : usize ,
188
- value_type_id : TypeId ,
189
117
default_value : String ,
190
- on_modify : OnModify ,
191
118
policy : Policy ,
192
119
}
193
120
194
121
impl IniEntity {
195
- pub ( crate ) fn new < T : TransformIniValue > (
122
+ pub ( crate ) fn new < T : IntoIniValue > (
196
123
name : impl Into < String > , default_value : T , policy : Policy ,
197
124
) -> Self {
198
- assert ! ( <T >:: arg2_size( ) <= size_of:: <usize >( ) ) ;
199
125
Self {
200
126
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 ( ) ,
205
128
policy,
206
129
}
207
130
}
208
131
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]
217
133
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 )
225
135
}
226
136
}
227
137
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 {
231
139
#[ cfg( any(
232
140
phper_php_version = "8.1" ,
233
141
phper_php_version = "8.0" ,
@@ -244,9 +152,9 @@ pub(crate) fn create_ini_entry_ex(
244
152
245
153
zend_ini_entry_def {
246
154
name : name. as_ptr ( ) . cast ( ) ,
247
- on_modify,
155
+ on_modify : None ,
248
156
mh_arg1 : null_mut ( ) ,
249
- mh_arg2 : arg2 ,
157
+ mh_arg2 : null_mut ( ) ,
250
158
mh_arg3 : null_mut ( ) ,
251
159
value : default_value. as_ptr ( ) . cast ( ) ,
252
160
displayer : None ,
@@ -255,3 +163,17 @@ pub(crate) fn create_ini_entry_ex(
255
163
value_length : default_value. len ( ) as u32 ,
256
164
}
257
165
}
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