@@ -15,10 +15,10 @@ use derive_more::From;
15
15
use std:: {
16
16
borrow:: Borrow ,
17
17
convert:: TryInto ,
18
- ffi:: c_void,
19
18
marker:: PhantomData ,
20
- mem:: { forget , ManuallyDrop } ,
19
+ mem:: ManuallyDrop ,
21
20
ops:: { Deref , DerefMut } ,
21
+ ptr:: null_mut,
22
22
} ;
23
23
24
24
/// Key for [ZArr].
@@ -112,8 +112,9 @@ impl ZArr {
112
112
113
113
/// Add or update item by key.
114
114
#[ allow( clippy:: useless_conversion) ]
115
- pub fn insert < ' a > ( & mut self , key : impl Into < InsertKey < ' a > > , mut value : ZVal ) {
115
+ pub fn insert < ' a > ( & mut self , key : impl Into < InsertKey < ' a > > , value : impl Into < ZVal > ) {
116
116
let key = key. into ( ) ;
117
+ let mut value = ManuallyDrop :: new ( value. into ( ) ) ;
117
118
let val = value. as_mut_ptr ( ) ;
118
119
119
120
unsafe {
@@ -150,8 +151,6 @@ impl ZArr {
150
151
}
151
152
}
152
153
}
153
-
154
- forget ( value) ;
155
154
}
156
155
157
156
// Get item by key.
@@ -244,21 +243,23 @@ impl ZArr {
244
243
}
245
244
}
246
245
247
- pub fn for_each < ' a > ( & self , f : impl FnMut ( IterKey < ' a > , & ' a ZVal ) ) {
248
- let mut f: Box < dyn FnMut ( IterKey < ' a > , & ' a ZVal ) > = Box :: new ( f) ;
249
- let f = & mut f as * mut Box < _ > as * mut c_void ;
250
- unsafe {
251
- phper_zend_hash_foreach_key_val ( self . as_ptr ( ) as * mut _ , Some ( for_each_callback) , f) ;
252
- }
253
- }
254
-
255
246
pub fn entry < ' a > ( & ' a mut self , key : impl Into < Key < ' a > > ) -> Entry < ' a > {
256
247
let key = key. into ( ) ;
257
248
match self . get_mut ( key. clone ( ) ) {
258
249
Some ( val) => Entry :: Occupied ( val) ,
259
250
None => Entry :: Vacant { arr : self , key } ,
260
251
}
261
252
}
253
+
254
+ #[ inline]
255
+ pub fn iter ( & self ) -> Iter < ' _ > {
256
+ Iter :: new ( self )
257
+ }
258
+
259
+ #[ inline]
260
+ pub fn iter_mut ( & mut self ) -> IterMut < ' _ > {
261
+ IterMut :: new ( self )
262
+ }
262
263
}
263
264
264
265
impl ToOwned for ZArr {
@@ -368,26 +369,114 @@ impl Drop for ZArray {
368
369
}
369
370
}
370
371
371
- /// Iterator key for [`ZArr::for_each `].
372
+ /// Iterator key for [`ZArr::iter`] and [`ZArr::iter_mut `].
372
373
#[ derive( Debug , Clone , PartialEq , From ) ]
373
374
pub enum IterKey < ' a > {
374
375
Index ( u64 ) ,
375
376
ZStr ( & ' a ZStr ) ,
376
377
}
377
378
378
- #[ allow( clippy:: unnecessary_cast) ]
379
- unsafe extern "C" fn for_each_callback (
380
- idx : zend_ulong , key : * mut zend_string , val : * mut zval , argument : * mut c_void ,
381
- ) {
382
- let f = ( argument as * mut Box < dyn FnMut ( IterKey < ' _ > , & ' _ ZVal ) > )
383
- . as_mut ( )
384
- . unwrap ( ) ;
385
- let iter_key = if key. is_null ( ) {
386
- IterKey :: Index ( idx as u64 )
387
- } else {
388
- IterKey :: ZStr ( ZStr :: from_ptr ( key) )
389
- } ;
390
- f ( iter_key, ZVal :: from_ptr ( val) ) ;
379
+ struct RawIter < ' a > {
380
+ arr : * mut zend_array ,
381
+ pos : HashPosition ,
382
+ finished : bool ,
383
+ _p : PhantomData < & ' a ( ) > ,
384
+ }
385
+
386
+ impl < ' a > RawIter < ' a > {
387
+ fn new ( arr : * mut zend_array ) -> Self {
388
+ let mut pos: HashPosition = 0 ;
389
+ unsafe {
390
+ zend_hash_internal_pointer_reset_ex ( arr, & mut pos) ;
391
+ }
392
+ Self {
393
+ arr,
394
+ pos,
395
+ finished : false ,
396
+ _p : PhantomData ,
397
+ }
398
+ }
399
+ }
400
+
401
+ impl < ' a > Iterator for RawIter < ' a > {
402
+ type Item = ( IterKey < ' a > , * mut zval ) ;
403
+
404
+ fn next ( & mut self ) -> Option < Self :: Item > {
405
+ unsafe {
406
+ if self . finished {
407
+ return None ;
408
+ }
409
+
410
+ let mut str_index: * mut zend_string = null_mut ( ) ;
411
+ let mut num_index: zend_ulong = 0 ;
412
+
413
+ #[ allow( clippy:: unnecessary_mut_passed) ]
414
+ let result = zend_hash_get_current_key_ex (
415
+ self . arr ,
416
+ & mut str_index,
417
+ & mut num_index,
418
+ & mut self . pos ,
419
+ ) as u32 ;
420
+
421
+ let iter_key = if result == HASH_KEY_IS_STRING {
422
+ IterKey :: ZStr ( ZStr :: from_mut_ptr ( str_index) )
423
+ } else if result == HASH_KEY_IS_LONG {
424
+ #[ allow( clippy:: unnecessary_cast) ]
425
+ IterKey :: Index ( num_index as u64 )
426
+ } else {
427
+ self . finished = true ;
428
+ return None ;
429
+ } ;
430
+
431
+ let val = zend_hash_get_current_data_ex ( self . arr , & mut self . pos ) ;
432
+ if val. is_null ( ) {
433
+ self . finished = true ;
434
+ return None ;
435
+ }
436
+
437
+ if zend_hash_move_forward_ex ( self . arr , & mut self . pos ) == ZEND_RESULT_CODE_FAILURE {
438
+ self . finished = true ;
439
+ }
440
+
441
+ Some ( ( iter_key, val) )
442
+ }
443
+ }
444
+ }
445
+
446
+ pub struct Iter < ' a > ( RawIter < ' a > ) ;
447
+
448
+ impl < ' a > Iter < ' a > {
449
+ fn new ( arr : & ' a ZArr ) -> Self {
450
+ Self ( RawIter :: new ( arr. as_ptr ( ) as * mut _ ) )
451
+ }
452
+ }
453
+
454
+ impl < ' a > Iterator for Iter < ' a > {
455
+ type Item = ( IterKey < ' a > , & ' a ZVal ) ;
456
+
457
+ fn next ( & mut self ) -> Option < Self :: Item > {
458
+ self . 0
459
+ . next ( )
460
+ . map ( |( key, val) | ( key, unsafe { ZVal :: from_ptr ( val) } ) )
461
+ }
462
+ }
463
+
464
+ pub struct IterMut < ' a > ( RawIter < ' a > ) ;
465
+
466
+ impl < ' a > IterMut < ' a > {
467
+ fn new ( arr : & ' a mut ZArr ) -> Self {
468
+ Self ( RawIter :: new ( arr. as_mut_ptr ( ) ) )
469
+ }
470
+ }
471
+
472
+ impl < ' a > Iterator for IterMut < ' a > {
473
+ type Item = ( IterKey < ' a > , & ' a mut ZVal ) ;
474
+
475
+ fn next ( & mut self ) -> Option < Self :: Item > {
476
+ self . 0
477
+ . next ( )
478
+ . map ( |( key, val) | ( key, unsafe { ZVal :: from_mut_ptr ( val) } ) )
479
+ }
391
480
}
392
481
393
482
pub enum Entry < ' a > {
0 commit comments