@@ -3,8 +3,7 @@ use std::fmt;
33
44use crate :: function:: { KwArgs , OptionalArg } ;
55use crate :: pyobject:: {
6- IdProtocol , IntoPyObject , ItemProtocol , PyAttributes , PyContext , PyObjectRef , PyRef , PyResult ,
7- PyValue ,
6+ IntoPyObject , ItemProtocol , PyAttributes , PyContext , PyObjectRef , PyRef , PyResult , PyValue ,
87} ;
98use crate :: vm:: { ReprGuard , VirtualMachine } ;
109
@@ -63,9 +62,8 @@ impl PyDictRef {
6362 if let OptionalArg :: Present ( dict_obj) = dict_obj {
6463 let dicted: PyResult < PyDictRef > = dict_obj. clone ( ) . downcast ( ) ;
6564 if let Ok ( dict_obj) = dicted {
66- let mut dict_borrowed = dict. borrow_mut ( ) ;
67- for ( key, value) in dict_obj. entries . borrow ( ) . iter_items ( ) {
68- dict_borrowed. insert ( vm, & key, value) ?;
65+ for ( key, value) in dict_obj {
66+ dict. borrow_mut ( ) . insert ( vm, & key, value) ?;
6967 }
7068 } else {
7169 let iter = objiter:: get_iter ( vm, & dict_obj) ?;
@@ -105,7 +103,7 @@ impl PyDictRef {
105103 fn repr ( self , vm : & VirtualMachine ) -> PyResult < String > {
106104 let s = if let Some ( _guard) = ReprGuard :: enter ( self . as_object ( ) ) {
107105 let mut str_parts = vec ! [ ] ;
108- for ( key, value) in self . get_key_value_pairs ( ) {
106+ for ( key, value) in self {
109107 let key_repr = vm. to_repr ( & key) ?;
110108 let value_repr = vm. to_repr ( & value) ?;
111109 str_parts. push ( format ! ( "{}: {}" , key_repr. value, value_repr. value) ) ;
@@ -146,10 +144,6 @@ impl PyDictRef {
146144 PyDictItems :: new ( self )
147145 }
148146
149- pub fn get_key_value_pairs ( & self ) -> Vec < ( PyObjectRef , PyObjectRef ) > {
150- self . entries . borrow ( ) . get_items ( )
151- }
152-
153147 fn inner_setitem (
154148 self ,
155149 key : PyObjectRef ,
@@ -194,24 +188,17 @@ impl PyDictRef {
194188
195189 fn update (
196190 self ,
197- mut dict_obj : OptionalArg < PyObjectRef > ,
191+ dict_obj : OptionalArg < PyObjectRef > ,
198192 kwargs : KwArgs ,
199193 vm : & VirtualMachine ,
200194 ) -> PyResult < ( ) > {
201- if let OptionalArg :: Present ( ref other) = dict_obj {
202- if self . is ( other) {
203- // Updating yourself is a noop, and this avoids a borrow error
204- dict_obj = OptionalArg :: Missing ;
205- }
206- }
207-
208195 PyDictRef :: merge ( & self . entries , dict_obj, kwargs, vm)
209196 }
210197
211198 /// Take a python dictionary and convert it to attributes.
212199 pub fn to_attributes ( self ) -> PyAttributes {
213200 let mut attrs = PyAttributes :: new ( ) ;
214- for ( key, value) in self . get_key_value_pairs ( ) {
201+ for ( key, value) in self {
215202 let key = objstr:: get_value ( & key) ;
216203 attrs. insert ( key, value) ;
217204 }
@@ -247,6 +234,54 @@ impl ItemProtocol for PyDictRef {
247234 }
248235}
249236
237+ // Implement IntoIterator so that we can easily iterate dictionaries from rust code.
238+ impl IntoIterator for PyDictRef {
239+ type Item = ( PyObjectRef , PyObjectRef ) ;
240+ type IntoIter = DictIterator ;
241+
242+ fn into_iter ( self ) -> Self :: IntoIter {
243+ DictIterator :: new ( self )
244+ }
245+ }
246+
247+ impl IntoIterator for & PyDictRef {
248+ type Item = ( PyObjectRef , PyObjectRef ) ;
249+ type IntoIter = DictIterator ;
250+
251+ fn into_iter ( self ) -> Self :: IntoIter {
252+ DictIterator :: new ( self . clone ( ) )
253+ }
254+ }
255+
256+ pub struct DictIterator {
257+ dict : PyDictRef ,
258+ position : Cell < usize > ,
259+ }
260+
261+ impl DictIterator {
262+ pub fn new ( dict : PyDictRef ) -> DictIterator {
263+ DictIterator {
264+ dict,
265+ position : Cell :: new ( 0 ) ,
266+ }
267+ }
268+ }
269+
270+ impl Iterator for DictIterator {
271+ type Item = ( PyObjectRef , PyObjectRef ) ;
272+
273+ fn next ( & mut self ) -> Option < Self :: Item > {
274+ self . dict
275+ . entries
276+ . borrow ( )
277+ . next_entry ( self . position . get ( ) )
278+ . map ( |( new_position, key, value) | {
279+ self . position . set ( new_position) ;
280+ ( key. clone ( ) , value. clone ( ) )
281+ } )
282+ }
283+ }
284+
250285macro_rules! dict_iterator {
251286 ( $name: ident, $iter_name: ident, $class: ident, $iter_class: ident, $class_name: literal, $iter_class_name: literal, $result_fn: expr) => {
252287 #[ pyclass( name = $class_name, __inside_vm) ]
0 commit comments