Skip to content

Commit 93bb600

Browse files
committed
Add Dictionary::at()
1 parent a1cf2a2 commit 93bb600

File tree

2 files changed

+55
-10
lines changed

2 files changed

+55
-10
lines changed

godot-core/src/builtin/dictionary.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,26 +100,51 @@ impl Dictionary {
100100
}
101101
}
102102

103+
/// ⚠️ Returns the value for the given key, or panics.
104+
///
105+
/// If you want to check for presence, use [`get()`][Self::get] or [`get_or_nil()`][Self::get_or_nil].
106+
///
107+
/// # Panics
108+
///
109+
/// If there is no value for the given key. Note that this is distinct from a `NIL` value, which is returned as `Variant::nil()`.
110+
pub fn at<K: ToGodot>(&self, key: K) -> Variant {
111+
// Code duplication with get(), to avoid third clone (since K: ToGodot takes ownership).
112+
113+
let key = key.to_variant();
114+
if self.contains_key(key.clone()) {
115+
self.get_or_nil(key)
116+
} else {
117+
panic!("key {key:?} missing in dictionary: {self:?}")
118+
}
119+
}
120+
103121
/// Returns the value for the given key, or `None`.
104122
///
105123
/// Note that `NIL` values are returned as `Some(Variant::nil())`, while absent values are returned as `None`.
106-
/// If you want to treat both as `NIL`, use [`Self::get_or_nil`].
124+
/// If you want to treat both as `NIL`, use [`get_or_nil()`][Self::get_or_nil].
125+
///
126+
/// When you are certain that a key is present, use [`at()`][`Self::at`] instead.
127+
///
128+
/// This can be combined with Rust's `Option` methods, e.g. `dict.get(key).unwrap_or(default)`.
107129
pub fn get<K: ToGodot>(&self, key: K) -> Option<Variant> {
130+
// If implementation is changed, make sure to update at().
131+
108132
let key = key.to_variant();
109-
if !self.contains_key(key.clone()) {
110-
return None;
133+
if self.contains_key(key.clone()) {
134+
Some(self.get_or_nil(key))
135+
} else {
136+
None
111137
}
112-
113-
Some(self.get_or_nil(key))
114138
}
115139

116140
/// Returns the value at the key in the dictionary, or `NIL` otherwise.
117141
///
118142
/// This method does not let you differentiate `NIL` values stored as values from absent keys.
119-
/// If you need that, use [`Self::get`].
143+
/// If you need that, use [`get()`][`Self::get`] instead.
144+
///
145+
/// When you are certain that a key is present, use [`at()`][`Self::at`] instead.
120146
///
121147
/// _Godot equivalent: `dict.get(key, null)`_
122-
#[doc(alias = "get")]
123148
pub fn get_or_nil<K: ToGodot>(&self, key: K) -> Variant {
124149
self.as_inner().get(key.to_variant(), Variant::nil())
125150
}

itest/rust/src/builtin_tests/containers/dictionary_test.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,29 +165,29 @@ fn dictionary_duplicate_shallow() {
165165
"foo": 0,
166166
"bar": subdictionary.clone()
167167
};
168+
168169
let mut clone = dictionary.duplicate_shallow();
169170
Dictionary::from_variant(&clone.get("bar").unwrap()).insert("baz", 4);
170171
assert_eq!(
171172
subdictionary.get("baz"),
172173
Some(4.to_variant()),
173174
"key = \"baz\""
174175
);
176+
175177
clone.insert("foo", false.to_variant());
176178
assert_eq!(dictionary.get("foo"), Some(0.to_variant()));
177179
assert_eq!(clone.get("foo"), Some(false.to_variant()));
178180
}
179181

180182
#[itest]
181183
fn dictionary_get() {
182-
let mut dictionary = dict! {
184+
let dictionary = dict! {
183185
"foo": 0,
184186
"bar": true,
185187
"baz": "foobar",
186188
"nil": Variant::nil(),
187189
};
188190

189-
dictionary.insert("baz", "foobar");
190-
191191
assert_eq!(dictionary.get("foo"), Some(0.to_variant()), "key = \"foo\"");
192192
assert_eq!(
193193
dictionary.get("bar"),
@@ -210,6 +210,26 @@ fn dictionary_get() {
210210
assert_eq!(dictionary.get("foobar"), None, "key = \"foobar\"");
211211
}
212212

213+
#[itest]
214+
fn dictionary_at() {
215+
let dictionary = dict! {
216+
"foo": 0,
217+
"baz": "foobar",
218+
"nil": Variant::nil(),
219+
};
220+
221+
assert_eq!(dictionary.at("foo"), 0.to_variant(), "key = \"foo\"");
222+
assert_eq!(
223+
dictionary.at("baz"),
224+
"foobar".to_variant(),
225+
"key = \"baz\""
226+
);
227+
assert_eq!(dictionary.at("nil"), Variant::nil(), "key = \"nil\"");
228+
expect_panic("key = \"bar\"", || {
229+
dictionary.at("bar");
230+
});
231+
}
232+
213233
#[itest]
214234
fn dictionary_insert() {
215235
let mut dictionary = dict! {

0 commit comments

Comments
 (0)