66
77use godot_ffi as sys;
88
9- use crate :: builtin:: { inner, FromVariant , ToVariant , Variant , VariantConversionError } ;
9+ use crate :: builtin:: { inner, FromVariant , ToVariant , Variant } ;
1010use crate :: obj:: Share ;
11- use std:: collections:: { HashMap , HashSet } ;
1211use std:: fmt;
13- use sys:: types:: * ;
12+ use std:: marker:: PhantomData ;
13+ use std:: ptr:: addr_of_mut;
14+ use sys:: types:: OpaqueDictionary ;
1415use sys:: { ffi_methods, interface_fn, GodotFfi } ;
1516
1617use super :: Array ;
@@ -134,12 +135,12 @@ impl Dictionary {
134135 }
135136
136137 /// Creates a new `Array` containing all the keys currently in the dictionary.
137- pub fn keys ( & self ) -> Array {
138+ pub fn keys_array ( & self ) -> Array {
138139 self . as_inner ( ) . keys ( )
139140 }
140141
141142 /// Creates a new `Array` containing all the values currently in the dictionary.
142- pub fn values ( & self ) -> Array {
143+ pub fn values_array ( & self ) -> Array {
143144 self . as_inner ( ) . values ( )
144145 }
145146
@@ -195,6 +196,28 @@ impl Dictionary {
195196 }
196197 }
197198
199+ /// Returns an iterator over the key-value pairs of the `Dictionary`. The pairs are each of type `(Variant, Variant)`.
200+ /// Each pair references the original `Dictionary`, but instead of a `&`-reference to key-value pairs as
201+ /// you might expect, the iterator returns a (cheap, shallow) copy of each key-value pair.
202+ ///
203+ /// Note that it's possible to modify the `Dictionary` through another reference while iterating
204+ /// over it. This will not result in unsoundness or crashes, but will cause the iterator to
205+ /// behave in an unspecified way.
206+ pub fn iter_shared ( & self ) -> Iter < ' _ > {
207+ Iter :: new ( self )
208+ }
209+
210+ /// Returns an iterator over the keys `Dictionary`. The keys are each of type `Variant`. Each key references
211+ /// the original `Dictionary`, but instead of a `&`-reference to keys pairs as you might expect, the
212+ /// iterator returns a (cheap, shallow) copy of each key pair.
213+ ///
214+ /// Note that it's possible to modify the `Dictionary` through another reference while iterating
215+ /// over it. This will not result in unsoundness or crashes, but will cause the iterator to
216+ /// behave in an unspecified way.
217+ pub fn keys_shared ( & self ) -> Keys < ' _ > {
218+ Keys :: new ( self )
219+ }
220+
198221 #[ doc( hidden) ]
199222 pub fn as_inner ( & self ) -> inner:: InnerDictionary {
200223 inner:: InnerDictionary :: from_outer ( self )
@@ -217,41 +240,6 @@ where
217240 }
218241}
219242
220- /// Convert this dictionary to a strongly typed rust `HashMap`. If the conversion
221- /// fails for any key or value, an error is returned.
222- ///
223- /// Will be replaced by a proper iteration implementation.
224- impl < K : FromVariant + Eq + std:: hash:: Hash , V : FromVariant > TryFrom < & Dictionary > for HashMap < K , V > {
225- type Error = VariantConversionError ;
226-
227- fn try_from ( dictionary : & Dictionary ) -> Result < Self , Self :: Error > {
228- // TODO: try to panic or something if modified while iterating
229- // Though probably better to fix when implementing iteration proper
230- dictionary
231- . keys ( )
232- . iter_shared ( )
233- . zip ( dictionary. values ( ) . iter_shared ( ) )
234- . map ( |( key, value) | Ok ( ( K :: try_from_variant ( & key) ?, V :: try_from_variant ( & value) ?) ) )
235- . collect ( )
236- }
237- }
238-
239- /// Convert the keys of this dictionary to a strongly typed rust `HashSet`. If the
240- /// conversion fails for any key, an error is returned.
241- impl < K : FromVariant + Eq + std:: hash:: Hash > TryFrom < & Dictionary > for HashSet < K > {
242- type Error = VariantConversionError ;
243-
244- fn try_from ( dictionary : & Dictionary ) -> Result < Self , Self :: Error > {
245- // TODO: try to panic or something if modified while iterating
246- // Though probably better to fix when implementing iteration proper
247- dictionary
248- . keys ( )
249- . iter_shared ( )
250- . map ( |key| K :: try_from_variant ( & key) )
251- . collect ( )
252- }
253- }
254-
255243/// Inserts all key-values from the iterator into the dictionary,
256244/// replacing values with existing keys with new values returned
257245/// from the iterator.
@@ -320,6 +308,210 @@ impl Share for Dictionary {
320308 }
321309}
322310
311+ struct DictionaryIter < ' a > {
312+ last_key : Option < Variant > ,
313+ dictionary : & ' a Dictionary ,
314+ is_first : bool ,
315+ }
316+
317+ impl < ' a > DictionaryIter < ' a > {
318+ fn new ( dictionary : & ' a Dictionary ) -> Self {
319+ Self {
320+ last_key : None ,
321+ dictionary,
322+ is_first : true ,
323+ }
324+ }
325+
326+ fn call_init ( dictionary : & Dictionary ) -> Option < Variant > {
327+ // SAFETY:
328+ // `dictionary` is a valid `Dictionary` since we have a reference to it,
329+ // so this will call the implementation for dictionaries.
330+ // `variant` is an initialized and valid `Variant`.
331+ let variant: Variant = Variant :: nil ( ) ;
332+ unsafe { Self :: call_iter_fn ( interface_fn ! ( variant_iter_init) , dictionary, variant) }
333+ }
334+
335+ fn call_next ( dictionary : & Dictionary , last_key : Variant ) -> Option < Variant > {
336+ // SAFETY:
337+ // `dictionary` is a valid `Dictionary` since we have a reference to it,
338+ // so this will call the implementation for dictionaries.
339+ // `last_key` is an initialized and valid `Variant`, since we own a copy of it.
340+ unsafe { Self :: call_iter_fn ( interface_fn ! ( variant_iter_next) , dictionary, last_key) }
341+ }
342+
343+ /// # SAFETY:
344+ /// `iter_fn` must point to a valid function that interprets the parameters according to their type specification.
345+ unsafe fn call_iter_fn (
346+ iter_fn : unsafe extern "C" fn (
347+ sys:: GDExtensionConstVariantPtr ,
348+ sys:: GDExtensionVariantPtr ,
349+ * mut sys:: GDExtensionBool ,
350+ ) -> sys:: GDExtensionBool ,
351+ dictionary : & Dictionary ,
352+ next_var : Variant ,
353+ ) -> Option < Variant > {
354+ let dictionary = dictionary. to_variant ( ) ;
355+ let mut valid: u8 = 0 ;
356+
357+ let has_next = iter_fn (
358+ dictionary. var_sys ( ) ,
359+ next_var. var_sys ( ) ,
360+ addr_of_mut ! ( valid) ,
361+ ) ;
362+ let valid = u8_to_bool ( valid) ;
363+ let has_next = u8_to_bool ( has_next) ;
364+
365+ if has_next {
366+ assert ! ( valid) ;
367+ Some ( next_var)
368+ } else {
369+ None
370+ }
371+ }
372+
373+ fn next_key ( & mut self ) -> Option < Variant > {
374+ let new_key = if self . is_first {
375+ self . is_first = false ;
376+ Self :: call_init ( self . dictionary )
377+ } else {
378+ Self :: call_next ( self . dictionary , self . last_key . take ( ) ?)
379+ } ;
380+ self . last_key = new_key. clone ( ) ;
381+ new_key
382+ }
383+
384+ fn next_key_value ( & mut self ) -> Option < ( Variant , Variant ) > {
385+ let key = self . next_key ( ) ?;
386+ if !self . dictionary . contains_key ( key. clone ( ) ) {
387+ return None ;
388+ }
389+
390+ let value = self . dictionary . as_inner ( ) . get ( key. clone ( ) , Variant :: nil ( ) ) ;
391+ Some ( ( key, value) )
392+ }
393+ }
394+
395+ /// An iterator over key-value pairs from a `Dictionary`.
396+ ///
397+ /// See [Dictionary::iter_shared()] for more information about iteration over dictionaries.
398+ pub struct Iter < ' a > {
399+ iter : DictionaryIter < ' a > ,
400+ }
401+
402+ impl < ' a > Iter < ' a > {
403+ fn new ( dictionary : & ' a Dictionary ) -> Self {
404+ Self {
405+ iter : DictionaryIter :: new ( dictionary) ,
406+ }
407+ }
408+
409+ /// Creates an iterator that will convert each `(Variant, Variant)` key-value pair into
410+ /// a `(K,V)` key-value pair, panicking upon failure to convert.
411+ pub fn typed < K : FromVariant , V : FromVariant > ( self ) -> TypedIter < ' a , K , V > {
412+ TypedIter :: from_untyped ( self )
413+ }
414+ }
415+
416+ impl < ' a > Iterator for Iter < ' a > {
417+ type Item = ( Variant , Variant ) ;
418+
419+ fn next ( & mut self ) -> Option < Self :: Item > {
420+ self . iter . next_key_value ( )
421+ }
422+ }
423+
424+ /// An iterator over keys from a `Dictionary`.
425+ ///
426+ /// See [Dictionary::keys_shared()] for more information about iteration over dictionaries.
427+ pub struct Keys < ' a > {
428+ iter : DictionaryIter < ' a > ,
429+ }
430+
431+ impl < ' a > Keys < ' a > {
432+ fn new ( dictionary : & ' a Dictionary ) -> Self {
433+ Self {
434+ iter : DictionaryIter :: new ( dictionary) ,
435+ }
436+ }
437+
438+ /// Creates an iterator that will convert each `Variant` key into a key of type `K`,
439+ /// panicking upon failure to convert.
440+ pub fn typed < K : FromVariant > ( self ) -> TypedKeys < ' a , K > {
441+ TypedKeys :: from_untyped ( self )
442+ }
443+ }
444+ impl < ' a > Iterator for Keys < ' a > {
445+ type Item = Variant ;
446+
447+ fn next ( & mut self ) -> Option < Self :: Item > {
448+ self . iter . next_key ( )
449+ }
450+ }
451+
452+ /// An iterator over key-value pairs from a `Dictionary` that will attempt to convert each
453+ /// key-value pair into a `(K,V)`.
454+ ///
455+ /// See [Dictionary::iter_shared()] for more information about iteration over dictionaries.
456+ pub struct TypedIter < ' a , K , V > {
457+ iter : DictionaryIter < ' a > ,
458+ _k : PhantomData < K > ,
459+ _v : PhantomData < V > ,
460+ }
461+
462+ impl < ' a , K , V > TypedIter < ' a , K , V > {
463+ fn from_untyped ( value : Iter < ' a > ) -> Self {
464+ Self {
465+ iter : value. iter ,
466+ _k : PhantomData ,
467+ _v : PhantomData ,
468+ }
469+ }
470+ }
471+
472+ impl < ' a , K : FromVariant , V : FromVariant > Iterator for TypedIter < ' a , K , V > {
473+ type Item = ( K , V ) ;
474+
475+ fn next ( & mut self ) -> Option < Self :: Item > {
476+ self . iter
477+ . next_key_value ( )
478+ . map ( |( key, value) | ( K :: from_variant ( & key) , V :: from_variant ( & value) ) )
479+ }
480+ }
481+
482+ /// An iterator over keys from a `Dictionary` that will attempt to convert each key into a `K`.
483+ ///
484+ /// See [Dictionary::iter_shared()] for more information about iteration over dictionaries.
485+ pub struct TypedKeys < ' a , K > {
486+ iter : DictionaryIter < ' a > ,
487+ _k : PhantomData < K > ,
488+ }
489+
490+ impl < ' a , K > TypedKeys < ' a , K > {
491+ fn from_untyped ( value : Keys < ' a > ) -> Self {
492+ Self {
493+ iter : value. iter ,
494+ _k : PhantomData ,
495+ }
496+ }
497+ }
498+
499+ impl < ' a , K : FromVariant > Iterator for TypedKeys < ' a , K > {
500+ type Item = K ;
501+
502+ fn next ( & mut self ) -> Option < Self :: Item > {
503+ self . iter . next_key ( ) . map ( |k| K :: from_variant ( & k) )
504+ }
505+ }
506+
507+ fn u8_to_bool ( u : u8 ) -> bool {
508+ match u {
509+ 0 => false ,
510+ 1 => true ,
511+ _ => panic ! ( "Invalid boolean value {u}" ) ,
512+ }
513+ }
514+
323515/// Creates a new dictionary with the given keys and values, the syntax mirrors
324516/// Godot's dictionary creation syntax.
325517///
0 commit comments