@@ -69,21 +69,42 @@ impl<Access: ThreadAccess> Dictionary<Access> {
69
69
unsafe { ( get_api ( ) . godot_dictionary_has_all ) ( self . sys ( ) , keys. sys ( ) ) }
70
70
}
71
71
72
- /// Returns a copy of the value corresponding to the key.
72
+ /// Returns a copy of the value corresponding to the key if it exists .
73
73
#[ inline]
74
- pub fn get < K > ( & self , key : K ) -> Variant
74
+ pub fn get < K > ( & self , key : K ) -> Option < Variant >
75
75
where
76
76
K : ToVariant + ToVariantEq ,
77
+ {
78
+ let key = key. to_variant ( ) ;
79
+ self . contains ( & key) . then ( || self . get_or_nil ( key) )
80
+ }
81
+
82
+ /// Returns a copy of the value corresponding to the key, or `default` if it doesn't exist
83
+ #[ inline]
84
+ pub fn get_or < K , D > ( & self , default : D , key : K ) -> Variant
85
+ where
86
+ K : ToVariant + ToVariantEq ,
87
+ D : ToVariant + ToVariantEq ,
77
88
{
78
89
unsafe {
79
- Variant ( ( get_api ( ) . godot_dictionary_get ) (
90
+ Variant ( ( get_api ( ) . godot_dictionary_get_with_default ) (
80
91
self . sys ( ) ,
81
92
key. to_variant ( ) . sys ( ) ,
93
+ default. to_variant ( ) . sys ( ) ,
82
94
) )
83
95
}
84
96
}
85
97
86
- /// Update an existing element corresponding ot the key.
98
+ /// Returns a copy of the element corresponding to the key, or `Nil` if it doesn't exist.
99
+ #[ inline]
100
+ pub fn get_or_nil < K > ( & self , key : K ) -> Variant
101
+ where
102
+ K : ToVariant + ToVariantEq ,
103
+ {
104
+ self . get_or ( Variant :: new ( ) , key)
105
+ }
106
+
107
+ /// Update an existing element corresponding to the key.
87
108
///
88
109
/// # Panics
89
110
///
@@ -106,12 +127,14 @@ impl<Access: ThreadAccess> Dictionary<Access> {
106
127
}
107
128
}
108
129
109
- /// Returns a reference to the value corresponding to the key.
130
+ /// Returns a reference to the value corresponding to the key, inserting `Nil` first if
131
+ /// it does not exist.
110
132
///
111
133
/// # Safety
112
134
///
113
135
/// The returned reference is invalidated if the same container is mutated through another
114
- /// reference.
136
+ /// reference, and other references may be invalidated if the entry does not already exist
137
+ /// (which causes this function to insert `Nil` and thus possibly re-allocate).
115
138
///
116
139
/// `Variant` is reference-counted and thus cheaply cloned. Consider using `get` instead.
117
140
#[ inline]
@@ -125,13 +148,16 @@ impl<Access: ThreadAccess> Dictionary<Access> {
125
148
) )
126
149
}
127
150
128
- /// Returns a mutable reference to the value corresponding to the key.
151
+ /// Returns a mutable reference to the value corresponding to the key, inserting `Nil`
152
+ /// first if it does not exist.
129
153
///
130
154
/// # Safety
131
155
///
132
156
/// The returned reference is invalidated if the same container is mutated through another
133
- /// reference. It is possible to create two mutable references to the same memory location
134
- /// if the same `key` is provided, causing undefined behavior.
157
+ /// reference, and other references may be invalidated if the `key` does not already exist
158
+ /// (which causes this function to insert `Nil` and thus possibly re-allocate). It is also
159
+ /// possible to create two mutable references to the same memory location if the same `key`
160
+ /// is provided, causing undefined behavior.
135
161
#[ inline]
136
162
#[ allow( clippy:: mut_from_ref) ]
137
163
pub unsafe fn get_mut_ref < K > ( & self , key : K ) -> & mut Variant
@@ -266,6 +292,19 @@ impl Dictionary<Shared> {
266
292
pub unsafe fn clear ( & self ) {
267
293
( get_api ( ) . godot_dictionary_clear ) ( self . sys_mut ( ) )
268
294
}
295
+
296
+ /// Returns a copy of the value corresponding to the key, inserting `Nil` first if it does not exist.
297
+ #[ doc_variant_collection_safety]
298
+ #[ inline]
299
+ pub unsafe fn get_or_insert_nil < K > ( & self , key : K ) -> Variant
300
+ where
301
+ K : ToVariant + ToVariantEq ,
302
+ {
303
+ Variant ( ( get_api ( ) . godot_dictionary_get ) (
304
+ self . sys ( ) ,
305
+ key. to_variant ( ) . sys ( ) ,
306
+ ) )
307
+ }
269
308
}
270
309
271
310
/// Operations allowed on Dictionaries that may only be shared on the current thread.
@@ -327,6 +366,20 @@ impl<Access: LocalThreadAccess> Dictionary<Access> {
327
366
pub fn clear ( & self ) {
328
367
unsafe { ( get_api ( ) . godot_dictionary_clear ) ( self . sys_mut ( ) ) }
329
368
}
369
+
370
+ /// Returns a copy of the value corresponding to the key, inserting `Nil` first if it does not exist.
371
+ #[ inline]
372
+ pub fn get_or_insert_nil < K > ( & self , key : K ) -> Variant
373
+ where
374
+ K : ToVariant + ToVariantEq ,
375
+ {
376
+ unsafe {
377
+ Variant ( ( get_api ( ) . godot_dictionary_get ) (
378
+ self . sys ( ) ,
379
+ key. to_variant ( ) . sys ( ) ,
380
+ ) )
381
+ }
382
+ }
330
383
}
331
384
332
385
/// Operations allowed on unique Dictionaries.
@@ -425,7 +478,7 @@ unsafe fn iter_next<Access: ThreadAccess>(
425
478
None
426
479
} else {
427
480
let key = Variant :: cast_ref ( next_ptr) . clone ( ) ;
428
- let value = dic. get ( & key) ;
481
+ let value = dic. get_or_nil ( & key) ;
429
482
* last_key = Some ( key. clone ( ) ) ;
430
483
Some ( ( key, value) )
431
484
}
@@ -591,7 +644,7 @@ godot_test!(test_dictionary {
591
644
let mut iter_keys = HashSet :: new( ) ;
592
645
let expected_keys = [ "foo" , "bar" ] . iter( ) . map( |& s| s. to_string( ) ) . collect:: <HashSet <_>>( ) ;
593
646
for ( key, value) in & dict {
594
- assert_eq!( value, dict. get( & key) ) ;
647
+ assert_eq!( Some ( value) , dict. get( & key) ) ;
595
648
if !iter_keys. insert( key. to_string( ) ) {
596
649
panic!( "key is already contained in set: {:?}" , key) ;
597
650
}
0 commit comments