1
1
//! Apis relate to [crate::sys::zend_ini_entry_def].
2
2
3
- use crate :: sys:: {
4
- phper_zend_ini_mh, zend_ini_entry_def, OnUpdateBool , OnUpdateLong , OnUpdateReal ,
5
- OnUpdateString , PHP_INI_ALL , PHP_INI_PERDIR , PHP_INI_SYSTEM , PHP_INI_USER ,
3
+ use crate :: {
4
+ errors:: Error :: Type ,
5
+ sys:: {
6
+ phper_zend_ini_mh, zend_ini_entry_def, OnUpdateBool , OnUpdateLong , OnUpdateReal ,
7
+ OnUpdateString , PHP_INI_ALL , PHP_INI_PERDIR , PHP_INI_SYSTEM , PHP_INI_USER ,
8
+ } ,
6
9
} ;
10
+ use dashmap:: DashMap ;
11
+ use derive_more:: { From , TryInto } ;
7
12
use std:: {
13
+ any:: { Any , TypeId } ,
14
+ collections:: HashMap ,
15
+ convert:: TryFrom ,
8
16
ffi:: CStr ,
17
+ mem:: { size_of, transmute, transmute_copy, zeroed} ,
9
18
os:: raw:: { c_char, c_void} ,
10
19
ptr:: null_mut,
11
20
str,
12
21
} ;
13
22
14
- type OnModify = phper_zend_ini_mh ;
23
+ pub struct Ini ;
24
+
25
+ impl Ini {
26
+ thread_local ! {
27
+ static INI_ENTITIES : DashMap <String , IniEntity > = DashMap :: new( ) ;
28
+ }
29
+
30
+ pub fn add ( name : impl ToString , default_value : impl TransformIniValue , policy : Policy ) {
31
+ Self :: INI_ENTITIES . with ( |ini_entities| {
32
+ ini_entities. insert (
33
+ name. to_string ( ) ,
34
+ IniEntity :: new ( name, default_value, policy) ,
35
+ ) ;
36
+ } ) ;
37
+ }
38
+
39
+ fn get < T : TransformIniValue > ( name : & str ) -> Option < T > {
40
+ Self :: INI_ENTITIES . with ( |ini_entities| {
41
+ ini_entities
42
+ . get ( name)
43
+ . and_then ( |entity| entity. value ( ) . value ( ) )
44
+ } )
45
+ }
46
+
47
+ pub ( crate ) unsafe fn entries ( ) -> * const zend_ini_entry_def {
48
+ let mut entries = Vec :: new ( ) ;
49
+
50
+ Self :: INI_ENTITIES . with ( |ini_entities| {
51
+ for entity in ini_entities {
52
+ entries. push ( entity. value ( ) . entry ( ) ) ;
53
+ }
54
+ } ) ;
55
+
56
+ entries. push ( zeroed :: < zend_ini_entry_def > ( ) ) ;
57
+
58
+ Box :: into_raw ( entries. into_boxed_slice ( ) ) . cast ( )
59
+ }
60
+ }
61
+
62
+ pub type OnModify = phper_zend_ini_mh ;
15
63
16
64
#[ repr( u32 ) ]
17
65
#[ derive( Copy , Clone ) ]
@@ -22,89 +70,147 @@ pub enum Policy {
22
70
System = PHP_INI_SYSTEM ,
23
71
}
24
72
25
- pub ( crate ) struct StrPtrBox {
26
- inner : Box < * mut c_char > ,
27
- }
73
+ pub trait TransformIniValue : ToString + ' static {
74
+ fn on_modify ( & self ) -> OnModify ;
75
+
76
+ unsafe fn transform ( & self , data : usize ) -> Option < * mut c_void > ;
77
+
78
+ fn arg2_type ( & self ) -> TypeId ;
28
79
29
- impl StrPtrBox {
30
- pub ( crate ) unsafe fn to_string ( & self ) -> Result < String , str:: Utf8Error > {
31
- Ok ( CStr :: from_ptr ( * self . inner ) . to_str ( ) ?. to_string ( ) )
80
+ fn arg2_size ( & self ) -> usize ;
81
+
82
+ fn to_text ( & self ) -> String {
83
+ self . to_string ( )
32
84
}
33
85
}
34
86
35
- impl Default for StrPtrBox {
36
- fn default ( ) -> Self {
37
- Self {
38
- inner : Box :: new ( null_mut ( ) ) ,
39
- }
87
+ impl TransformIniValue for bool {
88
+ fn on_modify ( & self ) -> OnModify {
89
+ Some ( OnUpdateBool )
40
90
}
41
- }
42
91
43
- pub trait IniValue : Default {
44
- fn on_modify ( ) -> OnModify ;
92
+ unsafe fn transform ( & self , data : usize ) -> Option < * mut c_void > {
93
+ let b = data != 0 ;
94
+ Some ( Box :: into_raw ( Box :: new ( b) ) . cast ( ) )
95
+ }
45
96
46
- fn arg2 ( & mut self ) -> * mut c_void {
47
- & mut * self as * mut _ as * mut c_void
97
+ fn arg2_type ( & self ) -> TypeId {
98
+ TypeId :: of :: < bool > ( )
48
99
}
49
- }
50
100
51
- impl IniValue for bool {
52
- fn on_modify ( ) -> OnModify {
53
- Some ( OnUpdateBool )
101
+ fn arg2_size ( & self ) -> usize {
102
+ size_of :: < bool > ( )
54
103
}
55
104
}
56
105
57
- impl IniValue for i64 {
58
- fn on_modify ( ) -> OnModify {
106
+ impl TransformIniValue for i64 {
107
+ fn on_modify ( & self ) -> OnModify {
59
108
Some ( OnUpdateLong )
60
109
}
110
+
111
+ unsafe fn transform ( & self , data : usize ) -> Option < * mut c_void > {
112
+ let i = data as i64 ;
113
+ Some ( Box :: into_raw ( Box :: new ( i) ) . cast ( ) )
114
+ }
115
+
116
+ fn arg2_type ( & self ) -> TypeId {
117
+ TypeId :: of :: < i64 > ( )
118
+ }
119
+
120
+ fn arg2_size ( & self ) -> usize {
121
+ size_of :: < i64 > ( )
122
+ }
61
123
}
62
124
63
- impl IniValue for f64 {
64
- fn on_modify ( ) -> OnModify {
125
+ impl TransformIniValue for f64 {
126
+ fn on_modify ( & self ) -> OnModify {
65
127
Some ( OnUpdateReal )
66
128
}
129
+
130
+ unsafe fn transform ( & self , data : usize ) -> Option < * mut c_void > {
131
+ let f = data as f64 ;
132
+ Some ( Box :: into_raw ( Box :: new ( f) ) . cast ( ) )
133
+ }
134
+
135
+ fn arg2_type ( & self ) -> TypeId {
136
+ TypeId :: of :: < i64 > ( )
137
+ }
138
+
139
+ fn arg2_size ( & self ) -> usize {
140
+ size_of :: < i64 > ( )
141
+ }
67
142
}
68
143
69
- impl IniValue for StrPtrBox {
70
- fn on_modify ( ) -> OnModify {
144
+ impl TransformIniValue for String {
145
+ fn on_modify ( & self ) -> OnModify {
71
146
Some ( OnUpdateString )
72
147
}
73
148
74
- fn arg2 ( & mut self ) -> * mut c_void {
75
- Box :: as_mut ( & mut self . inner ) as * mut _ as * mut c_void
149
+ unsafe fn transform ( & self , data : usize ) -> Option < * mut c_void > {
150
+ let ptr = data as * mut c_char ;
151
+ CStr :: from_ptr ( ptr)
152
+ . to_str ( )
153
+ . ok ( )
154
+ . map ( |s| Box :: into_raw ( Box :: new ( s. to_owned ( ) ) ) . cast ( ) )
155
+ }
156
+
157
+ fn arg2_type ( & self ) -> TypeId {
158
+ TypeId :: of :: < * mut c_char > ( )
159
+ }
160
+
161
+ fn arg2_size ( & self ) -> usize {
162
+ size_of :: < * mut c_char > ( )
76
163
}
77
164
}
78
165
79
- pub ( crate ) struct IniEntity < T : IniValue > {
166
+ pub ( crate ) struct IniEntity {
80
167
name : String ,
81
- value : T ,
168
+ value : usize ,
82
169
default_value : String ,
170
+ transform : Box < dyn TransformIniValue > ,
83
171
policy : Policy ,
84
172
}
85
173
86
- impl < T : IniValue > IniEntity < T > {
87
- pub ( crate ) fn new ( name : impl ToString , default_value : impl ToString , policy : Policy ) -> Self {
174
+ impl IniEntity {
175
+ pub ( crate ) fn new < T : TransformIniValue > (
176
+ name : impl ToString ,
177
+ default_value : T ,
178
+ policy : Policy ,
179
+ ) -> Self {
180
+ assert ! ( default_value. arg2_size( ) <= size_of:: <usize >( ) ) ;
88
181
Self {
89
182
name : name. to_string ( ) ,
90
- value : Default :: default ( ) ,
91
- default_value : default_value. to_string ( ) ,
183
+ value : 0 ,
184
+ default_value : default_value. to_text ( ) ,
185
+ transform : Box :: new ( default_value) ,
92
186
policy,
93
187
}
94
188
}
95
189
96
- pub ( crate ) fn value ( & self ) -> & T {
97
- & self . value
190
+ pub ( crate ) fn value < T : TransformIniValue > ( & self ) -> Option < T > {
191
+ if self . transform . arg2_type ( ) != TypeId :: of :: < T > ( ) {
192
+ None
193
+ } else {
194
+ unsafe {
195
+ let ptr = self . transform . transform ( self . value ) ;
196
+ ptr. map ( |ptr| {
197
+ let b = Box :: from_raw ( ptr as * mut T ) ;
198
+ * b
199
+ } )
200
+ }
201
+ }
98
202
}
99
203
100
- pub ( crate ) unsafe fn ini_entry_def ( & mut self ) -> zend_ini_entry_def {
101
- create_ini_entry_ex (
102
- & self . name ,
103
- & self . default_value ,
104
- <T >:: on_modify ( ) ,
105
- self . policy as u32 ,
106
- self . value . arg2 ( ) ,
107
- )
204
+ pub ( crate ) fn entry ( & mut self ) -> zend_ini_entry_def {
205
+ unsafe {
206
+ create_ini_entry_ex (
207
+ & self . name ,
208
+ & self . default_value ,
209
+ self . transform . on_modify ( ) ,
210
+ self . policy as u32 ,
211
+ & mut self . value as * mut _ as * mut c_void ,
212
+ )
213
+ }
108
214
}
109
215
}
110
216
0 commit comments