@@ -69,21 +69,49 @@ impl<Access: ThreadAccess> Dictionary<Access> {
6969 unsafe { ( get_api ( ) . godot_dictionary_has_all ) ( self . sys ( ) , keys. sys ( ) ) }
7070 }
7171
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 .
7373 #[ inline]
74- pub fn get < K > ( & self , key : K ) -> Variant
74+ pub fn get < K > ( & self , key : K ) -> Option < Variant >
7575 where
7676 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 ,
7794 {
7895 unsafe {
79- Variant ( ( get_api ( ) . godot_dictionary_get ) (
96+ Variant ( ( get_api ( ) . godot_dictionary_get_with_default ) (
8097 self . sys ( ) ,
8198 key. to_variant ( ) . sys ( ) ,
99+ default. to_variant ( ) . sys ( ) ,
82100 ) )
83101 }
84102 }
85103
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.
87115 ///
88116 /// # Panics
89117 ///
@@ -106,12 +134,14 @@ impl<Access: ThreadAccess> Dictionary<Access> {
106134 }
107135 }
108136
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.
110139 ///
111140 /// # Safety
112141 ///
113142 /// 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).
115145 ///
116146 /// `Variant` is reference-counted and thus cheaply cloned. Consider using `get` instead.
117147 #[ inline]
@@ -125,13 +155,16 @@ impl<Access: ThreadAccess> Dictionary<Access> {
125155 ) )
126156 }
127157
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.
129160 ///
130161 /// # Safety
131162 ///
132163 /// 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.
135168 #[ inline]
136169 #[ allow( clippy:: mut_from_ref) ]
137170 pub unsafe fn get_mut_ref < K > ( & self , key : K ) -> & mut Variant
@@ -425,7 +458,7 @@ unsafe fn iter_next<Access: ThreadAccess>(
425458 None
426459 } else {
427460 let key = Variant :: cast_ref ( next_ptr) . clone ( ) ;
428- let value = dic. get ( & key) ;
461+ let value = dic. get_or_nil ( & key) ;
429462 * last_key = Some ( key. clone ( ) ) ;
430463 Some ( ( key, value) )
431464 }
@@ -591,7 +624,7 @@ godot_test!(test_dictionary {
591624 let mut iter_keys = HashSet :: new( ) ;
592625 let expected_keys = [ "foo" , "bar" ] . iter( ) . map( |& s| s. to_string( ) ) . collect:: <HashSet <_>>( ) ;
593626 for ( key, value) in & dict {
594- assert_eq!( value, dict. get( & key) ) ;
627+ assert_eq!( Some ( value) , dict. get( & key) ) ;
595628 if !iter_keys. insert( key. to_string( ) ) {
596629 panic!( "key is already contained in set: {:?}" , key) ;
597630 }
0 commit comments