@@ -69,21 +69,49 @@ 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
+ if self . contains ( & key) {
80
+ // This should never return the default Nil, but there isn't a safe way to otherwise check
81
+ // if the entry exists in a single API call.
82
+ Some ( self . get_or_nil ( key) )
83
+ } else {
84
+ None
85
+ }
86
+ }
87
+
88
+ /// Returns a copy of the value corresponding to the key, or `default` if it doesn't exist
89
+ #[ inline]
90
+ pub fn get_or < K , D > ( & self , key : K , default : D ) -> Variant
91
+ where
92
+ K : ToVariant + ToVariantEq ,
93
+ D : ToVariant ,
77
94
{
78
95
unsafe {
79
- Variant ( ( get_api ( ) . godot_dictionary_get ) (
96
+ Variant ( ( get_api ( ) . godot_dictionary_get_with_default ) (
80
97
self . sys ( ) ,
81
98
key. to_variant ( ) . sys ( ) ,
99
+ default. to_variant ( ) . sys ( ) ,
82
100
) )
83
101
}
84
102
}
85
103
86
- /// Update an existing element corresponding ot the key.
104
+ /// Returns a copy of the element corresponding to the key, or `Nil` if it doesn't exist.
105
+ /// Shorthand for `self.get_or(key, Variant::new())`.
106
+ #[ inline]
107
+ pub fn get_or_nil < K > ( & self , key : K ) -> Variant
108
+ where
109
+ K : ToVariant + ToVariantEq ,
110
+ {
111
+ self . get_or ( key, Variant :: new ( ) )
112
+ }
113
+
114
+ /// Update an existing element corresponding to the key.
87
115
///
88
116
/// # Panics
89
117
///
@@ -106,12 +134,14 @@ impl<Access: ThreadAccess> Dictionary<Access> {
106
134
}
107
135
}
108
136
109
- /// Returns a reference to the value corresponding to the key.
137
+ /// Returns a reference to the value corresponding to the key, inserting a `Nil` value first if
138
+ /// it does not exist.
110
139
///
111
140
/// # Safety
112
141
///
113
142
/// The returned reference is invalidated if the same container is mutated through another
114
- /// reference.
143
+ /// reference, and other references may be invalidated if the entry does not already exist
144
+ /// (which causes this function to insert `Nil` and thus possibly re-allocate).
115
145
///
116
146
/// `Variant` is reference-counted and thus cheaply cloned. Consider using `get` instead.
117
147
#[ inline]
@@ -125,13 +155,16 @@ impl<Access: ThreadAccess> Dictionary<Access> {
125
155
) )
126
156
}
127
157
128
- /// Returns a mutable reference to the value corresponding to the key.
158
+ /// Returns a mutable reference to the value corresponding to the key, inserting a `Nil` value
159
+ /// first if it does not exist.
129
160
///
130
161
/// # Safety
131
162
///
132
163
/// 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.
164
+ /// reference, and other references may be invalidated if the `key` does not already exist
165
+ /// (which causes this function to insert `Nil` and thus possibly re-allocate). It is also
166
+ /// possible to create two mutable references to the same memory location if the same `key`
167
+ /// is provided, causing undefined behavior.
135
168
#[ inline]
136
169
#[ allow( clippy:: mut_from_ref) ]
137
170
pub unsafe fn get_mut_ref < K > ( & self , key : K ) -> & mut Variant
@@ -425,7 +458,7 @@ unsafe fn iter_next<Access: ThreadAccess>(
425
458
None
426
459
} else {
427
460
let key = Variant :: cast_ref ( next_ptr) . clone ( ) ;
428
- let value = dic. get ( & key) ;
461
+ let value = dic. get_or_nil ( & key) ;
429
462
* last_key = Some ( key. clone ( ) ) ;
430
463
Some ( ( key, value) )
431
464
}
@@ -591,7 +624,7 @@ godot_test!(test_dictionary {
591
624
let mut iter_keys = HashSet :: new( ) ;
592
625
let expected_keys = [ "foo" , "bar" ] . iter( ) . map( |& s| s. to_string( ) ) . collect:: <HashSet <_>>( ) ;
593
626
for ( key, value) in & dict {
594
- assert_eq!( value, dict. get( & key) ) ;
627
+ assert_eq!( Some ( value) , dict. get( & key) ) ;
595
628
if !iter_keys. insert( key. to_string( ) ) {
596
629
panic!( "key is already contained in set: {:?}" , key) ;
597
630
}
0 commit comments