1
1
//! Apis relate to [crate::sys::zend_class_entry].
2
2
3
+ use once_cell:: sync:: OnceCell ;
3
4
use std:: {
4
5
any:: Any ,
5
- collections:: HashMap ,
6
6
convert:: Infallible ,
7
7
marker:: PhantomData ,
8
8
mem:: { size_of, zeroed, ManuallyDrop } ,
@@ -14,23 +14,22 @@ use std::{
14
14
} ,
15
15
} ;
16
16
17
- use dashmap:: DashMap ;
18
- use once_cell:: sync:: OnceCell ;
19
-
20
17
use phper_alloc:: EBox ;
21
18
22
19
use crate :: {
23
- errors:: { ClassNotFoundError , Throwable } ,
20
+ errors:: { ClassNotFoundError , StateTypeError , Throwable } ,
24
21
functions:: { Argument , FunctionEntity , FunctionEntry , Method } ,
25
22
objects:: { ExtendObject , Object } ,
26
23
sys:: * ,
27
24
utils:: ensure_end_with_zero,
28
25
values:: { SetVal , Val } ,
29
26
} ;
30
- use std:: rc:: Rc ;
27
+ use dashmap:: DashMap ;
28
+ use std:: { any:: TypeId , iter:: Once } ;
31
29
32
30
pub trait Classifiable {
33
31
fn state_constructor ( & self ) -> Box < StateConstructor < Box < dyn Any > > > ;
32
+ fn state_type_id ( & self ) -> TypeId ;
34
33
fn class_name ( & self ) -> & str ;
35
34
fn methods ( & mut self ) -> & mut [ FunctionEntity ] ;
36
35
fn properties ( & mut self ) -> & mut [ PropertyEntity ] ;
@@ -116,6 +115,10 @@ impl<T: Send + Sync> Classifiable for DynamicClass<T> {
116
115
Box :: new ( move || sc ( ) . map ( |x| Box :: new ( x) as _ ) )
117
116
}
118
117
118
+ fn state_type_id ( & self ) -> TypeId {
119
+ TypeId :: of :: < T > ( )
120
+ }
121
+
119
122
fn class_name ( & self ) -> & str {
120
123
& self . class_name
121
124
}
@@ -133,22 +136,42 @@ impl<T: Send + Sync> Classifiable for DynamicClass<T> {
133
136
}
134
137
}
135
138
139
+ /// Used to represent classes not registered by this framework,
140
+ /// or classes that do not have or do not want to process state.
141
+ pub type StatelessClassEntry = ClassEntry < ( ) > ;
142
+
136
143
/// Wrapper of [crate::sys::zend_class_entry].
137
- ///
138
- /// TODO Add generic type.
139
144
#[ repr( transparent) ]
140
- pub struct ClassEntry {
145
+ pub struct ClassEntry < T : ' static > {
141
146
inner : zend_class_entry ,
147
+ _p : PhantomData < T > ,
142
148
}
143
149
144
- impl ClassEntry {
145
- // TODO After added generic type, Check generic type is relate to class_name, otherwise return error.
146
- pub fn from_globals < ' a > ( class_name : impl AsRef < str > ) -> Result < & ' a Self , ClassNotFoundError > {
150
+ impl < T : ' static > ClassEntry < T > {
151
+ pub fn from_globals < ' a > ( class_name : impl AsRef < str > ) -> crate :: Result < & ' a Self > {
147
152
let name = class_name. as_ref ( ) ;
148
153
let ptr: * mut Self = find_global_class_entry_ptr ( name) . cast ( ) ;
149
- unsafe {
150
- ptr. as_ref ( )
151
- . ok_or_else ( || ClassNotFoundError :: new ( name. to_string ( ) ) )
154
+ let r = unsafe {
155
+ ptr. as_ref ( ) . ok_or_else ( || {
156
+ crate :: Error :: ClassNotFound ( ClassNotFoundError :: new ( name. to_string ( ) ) )
157
+ } )
158
+ } ;
159
+ Self :: check_type_id ( ptr) ;
160
+ r
161
+ }
162
+
163
+ fn check_type_id ( this : * mut Self ) -> Result < ( ) , StateTypeError > {
164
+ if TypeId :: of :: < T > ( ) == TypeId :: of :: < ( ) > ( ) {
165
+ return Ok ( ( ) ) ;
166
+ }
167
+ let is = get_registered_class_type_map ( )
168
+ . get ( & ( this as usize ) )
169
+ . map ( |t| * t == TypeId :: of :: < T > ( ) )
170
+ . unwrap_or_default ( ) ;
171
+ if is {
172
+ Ok ( ( ) )
173
+ } else {
174
+ Err ( StateTypeError )
152
175
}
153
176
}
154
177
@@ -164,7 +187,7 @@ impl ClassEntry {
164
187
& mut self . inner
165
188
}
166
189
167
- pub ( crate ) fn create_object < T > ( & self ) -> EBox < Object < T > > {
190
+ pub fn create_object ( & self ) -> EBox < Object < T > > {
168
191
unsafe {
169
192
let f = self . inner . __bindgen_anon_2 . create_object . unwrap ( ) ;
170
193
let object = f ( self . as_ptr ( ) as * mut _ ) ;
@@ -188,7 +211,7 @@ fn find_global_class_entry_ptr(name: impl AsRef<str>) -> *mut zend_class_entry {
188
211
189
212
pub struct ClassEntity {
190
213
pub ( crate ) name : String ,
191
- pub ( crate ) entry : AtomicPtr < ClassEntry > ,
214
+ pub ( crate ) entry : AtomicPtr < ClassEntry < Box < dyn Any > > > ,
192
215
pub ( crate ) classifiable : Box < dyn Classifiable > ,
193
216
pub ( crate ) function_entries : OnceCell < AtomicPtr < FunctionEntry > > ,
194
217
}
@@ -210,21 +233,23 @@ impl ClassEntity {
210
233
self . function_entries ( ) . load ( Ordering :: SeqCst ) . cast ( ) ,
211
234
) ;
212
235
213
- let parent = self
236
+ let parent: Option < & StatelessClassEntry > = self
214
237
. classifiable
215
238
. parent ( )
216
239
. map ( |s| ClassEntry :: from_globals ( s) . unwrap ( ) ) ;
217
240
218
- let class: * mut ClassEntry = match parent {
241
+ let class: * mut ClassEntry < ( ) > = match parent {
219
242
Some ( parent) => {
220
243
zend_register_internal_class_ex ( & mut class_ce, parent. as_ptr ( ) as * mut _ ) . cast ( )
221
244
}
222
245
None => zend_register_internal_class ( & mut class_ce) . cast ( ) ,
223
246
} ;
224
- self . entry . store ( class, Ordering :: SeqCst ) ;
247
+ // self.entry.store(class, Ordering::SeqCst);
225
248
226
249
( * class) . inner . __bindgen_anon_2 . create_object = Some ( create_object) ;
227
250
251
+ get_registered_class_type_map ( ) . insert ( class as usize , self . classifiable . state_type_id ( ) ) ;
252
+
228
253
// let classifiable = self.classifiable.clone();
229
254
// get_class_constructor_map().insert(class as usize, Box::new(move || classifiable.state_constructor()));
230
255
@@ -275,7 +300,7 @@ impl ClassEntity {
275
300
276
301
unsafe fn take_classifiable_into_function_entry ( & self ) -> zend_function_entry {
277
302
let mut entry = zeroed :: < zend_function_entry > ( ) ;
278
- let ptr = & mut entry as * mut _ as * mut ManuallyDrop < Box < StateConstructor < Box < Any > > > > ;
303
+ let ptr = & mut entry as * mut _ as * mut ManuallyDrop < Box < StateConstructor < Box < dyn Any > > > > ;
279
304
let state_constructor = ManuallyDrop :: new ( self . classifiable . state_constructor ( ) ) ;
280
305
ptr. write ( state_constructor) ;
281
306
entry
@@ -305,9 +330,14 @@ pub enum Visibility {
305
330
Private = ZEND_ACC_PRIVATE ,
306
331
}
307
332
333
+ fn get_registered_class_type_map ( ) -> & ' static DashMap < usize , TypeId > {
334
+ static MAP : OnceCell < DashMap < usize , TypeId > > = OnceCell :: new ( ) ;
335
+ MAP . get_or_init ( DashMap :: new)
336
+ }
337
+
308
338
fn get_object_handlers ( ) -> & ' static zend_object_handlers {
309
- static OBJECT_HANDLERS : OnceCell < zend_object_handlers > = OnceCell :: new ( ) ;
310
- OBJECT_HANDLERS . get_or_init ( || unsafe {
339
+ static HANDLERS : OnceCell < zend_object_handlers > = OnceCell :: new ( ) ;
340
+ HANDLERS . get_or_init ( || unsafe {
311
341
let mut handlers = std_object_handlers;
312
342
handlers. offset = ExtendObject :: offset ( ) as c_int ;
313
343
handlers. free_obj = Some ( free_object) ;
@@ -333,7 +363,7 @@ unsafe extern "C" fn create_object(ce: *mut zend_class_entry) -> *mut zend_objec
333
363
func_ptr = func_ptr. offset ( 1 ) ;
334
364
}
335
365
func_ptr = func_ptr. offset ( 1 ) ;
336
- let state_constructor = func_ptr as * const ManuallyDrop < Box < StateConstructor < Box < Any > > > > ;
366
+ let state_constructor = func_ptr as * const ManuallyDrop < Box < StateConstructor < Box < dyn Any > > > > ;
337
367
let state_constructor = state_constructor. read ( ) ;
338
368
339
369
// Call the state constructor.
0 commit comments