11use crate :: convert:: { FromZval , FromZvalMut } ;
2- use crate :: ffi:: zend_object_iterator;
2+ use crate :: ffi:: { zend_object_iterator, ZEND_RESULT_CODE_SUCCESS } ;
33use crate :: flags:: DataType ;
4+ use crate :: prelude:: PhpResult ;
45use crate :: types:: Zval ;
6+ use crate :: zend:: ExecutorGlobals ;
57use std:: fmt:: { Debug , Display , Formatter } ;
68
79/// A PHP Iterator.
@@ -16,47 +18,55 @@ impl ZendIterator {
1618 /// # Returns
1719 ///
1820 /// Returns a iterator over the zend_object_iterator.
19- pub fn iter ( & mut self ) -> Iter {
21+ pub fn iter ( & mut self ) -> PhpResult < Iter > {
2022 self . index = 0 ;
21- self . rewind ( ) ;
23+ self . rewind ( ) ? ;
2224
23- Iter { zi : self }
25+ Ok ( Iter { zi : self } )
2426 }
2527
2628 /// Check if the current position of the iterator is valid.
2729 ///
2830 /// As an example this will call the user defined valid method of the ['\Iterator'] interface.
2931 /// see <https://www.php.net/manual/en/iterator.valid.php>
30- pub fn valid ( & mut self ) -> bool {
32+ pub fn valid ( & mut self ) -> PhpResult < bool > {
3133 if let Some ( valid) = unsafe { ( * self . funcs ) . valid } {
32- unsafe { valid ( & mut * self ) != 0 }
34+ let valid = unsafe { valid ( & mut * self ) == ZEND_RESULT_CODE_SUCCESS } ;
35+
36+ ExecutorGlobals :: throw_if_exception ( ) ?;
37+
38+ Ok ( valid)
3339 } else {
34- true
40+ Ok ( true )
3541 }
3642 }
3743
3844 /// Rewind the iterator to the first element.
3945 ///
4046 /// As an example this will call the user defined rewind method of the ['\Iterator'] interface.
4147 /// see <https://www.php.net/manual/en/iterator.rewind.php>
42- pub fn rewind ( & mut self ) {
48+ pub fn rewind ( & mut self ) -> PhpResult < ( ) > {
4349 if let Some ( rewind) = unsafe { ( * self . funcs ) . rewind } {
4450 unsafe {
4551 rewind ( & mut * self ) ;
4652 }
4753 }
54+
55+ ExecutorGlobals :: throw_if_exception ( )
4856 }
4957
5058 /// Move the iterator forward to the next element.
5159 ///
5260 /// As an example this will call the user defined next method of the ['\Iterator'] interface.
5361 /// see <https://www.php.net/manual/en/iterator.next.php>
54- pub fn move_forward ( & mut self ) {
62+ pub fn move_forward ( & mut self ) -> PhpResult < ( ) > {
5563 if let Some ( move_forward) = unsafe { ( * self . funcs ) . move_forward } {
5664 unsafe {
5765 move_forward ( & mut * self ) ;
5866 }
5967 }
68+
69+ ExecutorGlobals :: throw_if_exception ( )
6070 }
6171
6272 /// Get the current data of the iterator.
@@ -65,11 +75,16 @@ impl ZendIterator {
6575 ///
6676 /// Returns a reference to the current data of the iterator if available
6777 /// , ['None'] otherwise.
68- pub fn get_current_data < ' a > ( & mut self ) -> Option < & ' a Zval > {
69- let get_current_data = unsafe { ( * self . funcs ) . get_current_data } ?;
78+ pub fn get_current_data < ' a > ( & mut self ) -> PhpResult < Option < & ' a Zval > > {
79+ let get_current_data = match unsafe { ( * self . funcs ) . get_current_data } {
80+ Some ( get_current_data) => get_current_data,
81+ None => return Ok ( None ) ,
82+ } ;
7083 let value = unsafe { & * get_current_data ( & mut * self ) } ;
7184
72- Some ( value)
85+ ExecutorGlobals :: throw_if_exception ( ) ?;
86+
87+ Ok ( Some ( value) )
7388 }
7489
7590 /// Get the current key of the iterator.
@@ -78,14 +93,21 @@ impl ZendIterator {
7893 ///
7994 /// Returns a new ['Zval'] containing the current key of the iterator if available
8095 /// , ['None'] otherwise.
81- pub fn get_current_key ( & mut self ) -> Option < Zval > {
82- let get_current_key = unsafe { ( * self . funcs ) . get_current_key } ?;
96+ pub fn get_current_key ( & mut self ) -> PhpResult < Option < Zval > > {
97+ let get_current_key = match unsafe { ( * self . funcs ) . get_current_key } {
98+ Some ( get_current_key) => get_current_key,
99+ None => return Ok ( None ) ,
100+ } ;
101+
83102 let mut key = Zval :: new ( ) ;
103+
84104 unsafe {
85105 get_current_key ( & mut * self , & mut key) ;
86106 }
87107
88- Some ( key)
108+ ExecutorGlobals :: throw_if_exception ( ) ?;
109+
110+ Ok ( Some ( key) )
89111 }
90112}
91113
@@ -142,31 +164,40 @@ pub struct Iter<'a> {
142164}
143165
144166impl < ' a > Iterator for Iter < ' a > {
145- type Item = ( IterKey , & ' a Zval ) ;
167+ type Item = PhpResult < ( IterKey , & ' a Zval ) > ;
146168
147169 fn next ( & mut self ) -> Option < Self :: Item > {
148170 // Call next when index > 0, so next is really called at the start of each iteration, which allow to work better with generator iterator
149171 if self . zi . index > 0 {
150- self . zi . move_forward ( ) ;
151-
152- if !self . zi . valid ( ) {
153- return None ;
172+ if let Err ( err) = self . zi . move_forward ( ) {
173+ return Some ( Err ( err) ) ;
154174 }
155175 }
156176
177+ match self . zi . valid ( ) {
178+ Err ( err) => return Some ( Err ( err) ) ,
179+ Ok ( false ) => return None ,
180+ Ok ( true ) => ( ) ,
181+ }
182+
157183 self . zi . index += 1 ;
158184
159- let key = self . zi . get_current_key ( ) ;
160- let value = self . zi . get_current_data ( ) ?;
161185 let real_index = self . zi . index - 1 ;
162186
163- Some ( match key {
164- Some ( key) => match IterKey :: from_zval ( & key) {
165- Some ( key) => ( key, value) ,
166- None => ( IterKey :: Long ( real_index) , value) ,
187+ let key = match self . zi . get_current_key ( ) {
188+ Err ( err) => return Some ( Err ( err) ) ,
189+ Ok ( None ) => IterKey :: Long ( real_index) ,
190+ Ok ( Some ( key) ) => match IterKey :: from_zval ( & key) {
191+ Some ( key) => key,
192+ None => IterKey :: Long ( real_index) ,
167193 } ,
168- None => ( IterKey :: Long ( real_index) , value) ,
169- } )
194+ } ;
195+
196+ match self . zi . get_current_data ( ) {
197+ Err ( err) => Some ( Err ( err) ) ,
198+ Ok ( None ) => None ,
199+ Ok ( Some ( value) ) => Some ( Ok ( ( key, value) ) ) ,
200+ }
170201 }
171202}
172203
0 commit comments