@@ -15,10 +15,10 @@ use derive_more::From;
1515use std:: {
1616 borrow:: Borrow ,
1717 convert:: TryInto ,
18- ffi:: c_void,
1918 marker:: PhantomData ,
20- mem:: { forget , ManuallyDrop } ,
19+ mem:: ManuallyDrop ,
2120 ops:: { Deref , DerefMut } ,
21+ ptr:: null_mut,
2222} ;
2323
2424/// Key for [ZArr].
@@ -112,8 +112,9 @@ impl ZArr {
112112
113113 /// Add or update item by key.
114114 #[ 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 > ) {
116116 let key = key. into ( ) ;
117+ let mut value = ManuallyDrop :: new ( value. into ( ) ) ;
117118 let val = value. as_mut_ptr ( ) ;
118119
119120 unsafe {
@@ -150,8 +151,6 @@ impl ZArr {
150151 }
151152 }
152153 }
153-
154- forget ( value) ;
155154 }
156155
157156 // Get item by key.
@@ -244,21 +243,23 @@ impl ZArr {
244243 }
245244 }
246245
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-
255246 pub fn entry < ' a > ( & ' a mut self , key : impl Into < Key < ' a > > ) -> Entry < ' a > {
256247 let key = key. into ( ) ;
257248 match self . get_mut ( key. clone ( ) ) {
258249 Some ( val) => Entry :: Occupied ( val) ,
259250 None => Entry :: Vacant { arr : self , key } ,
260251 }
261252 }
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+ }
262263}
263264
264265impl ToOwned for ZArr {
@@ -368,26 +369,114 @@ impl Drop for ZArray {
368369 }
369370}
370371
371- /// Iterator key for [`ZArr::for_each `].
372+ /// Iterator key for [`ZArr::iter`] and [`ZArr::iter_mut `].
372373#[ derive( Debug , Clone , PartialEq , From ) ]
373374pub enum IterKey < ' a > {
374375 Index ( u64 ) ,
375376 ZStr ( & ' a ZStr ) ,
376377}
377378
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+ }
391480}
392481
393482pub enum Entry < ' a > {
0 commit comments