Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions godot-core/src/builtin/collections/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,60 @@ use sys::{ffi_methods, interface_fn, GodotFfi};
/// If you want to create a copy of the data, use [`duplicate_shallow()`][Self::duplicate_shallow]
/// or [`duplicate_deep()`][Self::duplicate_deep].
///
/// # Typed array example
///
/// ```no_run
/// # use godot::prelude::*;
/// // Create typed Array<i64> and add values.
/// let mut array = Array::new();
/// array.push(10);
/// array.push(20);
/// array.push(30);
///
/// // Or create the same array in a single expression.
/// let array = array![10, 20, 30];
///
/// // Access elements.
/// let value: i64 = array.at(0); // 10
/// let maybe: Option<i64> = array.get(3); // None
///
/// // Iterate over i64 elements.
/// for value in array.iter_shared() {
/// println!("{value}");
/// }
///
/// // Clone array (shares the reference), and overwrite elements through clone.
/// let mut cloned = array.clone();
/// cloned.set(0, 50); // [50, 20, 30]
/// cloned.remove(1); // [50, 30]
/// cloned.pop(); // [50]
///
/// // Changes will be reflected in the original array.
/// assert_eq!(array.len(), 1);
/// assert_eq!(array.front(), Some(50));
/// ```
///
/// # Untyped array example
///
/// ```no_run
/// # use godot::prelude::*;
/// // VariantArray allows dynamic element types.
/// let mut array = VariantArray::new();
/// array.push(10.to_variant());
/// array.push("Hello".to_variant());
///
/// // Or equivalent, use the `varray!` macro which converts each element.
/// let array = varray![10, "Hello"];
///
/// // Access elements.
/// let value: Variant = array.at(0);
/// let value: i64 = array.at(0).to(); // Variant::to() extracts i64.
/// let maybe: Result<i64, _> = array.at(1).try_to(); // "Hello" is not i64 -> Err.
/// let maybe: Option<Variant> = array.get(3);
///
/// // ...and so on.
/// ```
///
/// # Thread safety
///
/// Usage is safe if the `Array` is used on a single thread only. Concurrent reads on
Expand Down
52 changes: 50 additions & 2 deletions godot-core/src/builtin/collections/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,53 @@ use std::{fmt, ptr};
/// The keys and values of the dictionary are all `Variant`s, so they can be of different types.
/// Variants are designed to be generally cheap to clone.
///
/// # Dictionary example
///
/// ```no_run
/// # use godot::prelude::*;
/// // Create empty dictionary and add key-values pairs.
/// let mut dict = Dictionary::new();
/// dict.set("str", "Hello");
/// dict.set("num", 23);
///
/// // Keys don't need to be strings.
/// let coord = Vector2i::new(0, 1);
/// dict.set(coord, "Tile77");
///
/// // Or create the same dictionary in a single expression.
/// let dict = dict! {
/// "str": "Hello",
/// "num": 23,
/// coord: "Tile77",
/// };
///
/// // Access elements.
/// let value: Variant = dict.at("str");
/// let value: GString = dict.at("str").to(); // Variant::to() extracts GString.
/// let maybe: Option<Variant> = dict.get("absent_key");
///
/// // Iterate over key-value pairs as (Variant, Variant).
/// for (key, value) in dict.iter_shared() {
/// println!("{key} => {value}");
/// }
///
/// // Use typed::<K, V>() to get typed iterators.
/// for (key, value) in dict.iter_shared().typed::<GString, Variant>() {
/// println!("{key} => {value}");
/// }
///
/// // Clone dictionary (shares the reference), and overwrite elements through clone.
/// let mut cloned = dict.clone();
/// cloned.remove("num");
///
/// // Overwrite with set(); use insert() to get the previous value.
/// let prev = cloned.insert("str", "Goodbye"); // prev == Some("Hello")
///
/// // Changes will be reflected in the original dictionary.
/// assert_eq!(dict.at("str"), "Goodbye".to_variant());
/// assert_eq!(dict.get("num"), None);
/// ```
///
/// # Thread safety
///
/// The same principles apply as for [`VariantArray`]. Consult its documentation for details.
Expand Down Expand Up @@ -160,6 +207,7 @@ impl Dictionary {
/// Insert a value at the given key, returning the previous value for that key (if available).
///
/// If you don't need the previous value, use [`set()`][Self::set] instead.
#[must_use]
pub fn insert<K: ToGodot, V: ToGodot>(&mut self, key: K, value: V) -> Option<Variant> {
let key = key.to_variant();
let old_value = self.get(key.clone());
Expand Down Expand Up @@ -245,7 +293,7 @@ impl Dictionary {
/// Note that it's possible to modify the `Dictionary` through another reference while iterating over it. This will not result in
/// unsoundness or crashes, but will cause the iterator to behave in an unspecified way.
///
/// Use `iter_shared().typed::<K, V>()` to iterate over `(K, V)` pairs instead.
/// Use `dict.iter_shared().typed::<K, V>()` to iterate over `(K, V)` pairs instead.
pub fn iter_shared(&self) -> Iter<'_> {
Iter::new(self)
}
Expand All @@ -258,7 +306,7 @@ impl Dictionary {
/// Note that it's possible to modify the `Dictionary` through another reference while iterating over it. This will not result in
/// unsoundness or crashes, but will cause the iterator to behave in an unspecified way.
///
/// Use `.keys_shared.typed::<K>()` to iterate over `K` keys instead.
/// Use `dict.keys_shared().typed::<K>()` to iterate over `K` keys instead.
pub fn keys_shared(&self) -> Keys<'_> {
Keys::new(self)
}
Expand Down
3 changes: 3 additions & 0 deletions godot-core/src/builtin/quaternion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use crate::builtin::math::{ApproxEq, FloatExt, GlamConv, GlamType};
use crate::builtin::{inner, real, Basis, EulerOrder, RQuat, RealConv, Vector3};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};

/// Unit quaternion to represent 3D rotations.
///
/// See also [`Quaternion`](https://docs.godotengine.org/en/stable/classes/class_quaternion.html) in the Godot documentation.
#[derive(Copy, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
Expand Down
4 changes: 2 additions & 2 deletions godot-core/src/engine/mod.rs → godot-core/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ pub use crate::obj::script::SiMut;
#[deprecated = "`GFile` has been moved to `godot::tools`."]
pub use crate::tools::GFile;

#[deprecated = "`IoError` has been moved to `godot::tools`."]
pub use crate::tools::IoError;
#[deprecated = "`IoError` has been moved to `godot::meta::error`."]
pub use crate::meta::error::IoError;

#[deprecated = "`save` has been moved to `godot::global`."]
pub use crate::tools::save;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use std::error::Error;
use std::fmt;

use crate::gen::classes::FileAccess;
use crate::classes::FileAccess;
use crate::global::Error as GodotError;
use crate::obj::Gd;

Expand Down
2 changes: 2 additions & 0 deletions godot-core/src/meta/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

mod call_error;
mod convert_error;
mod io_error;

pub use call_error::*;
pub use convert_error::*;
pub use io_error::*;
2 changes: 1 addition & 1 deletion godot-core/src/tools/gfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use crate::classes::file_access::{CompressionMode, ModeFlags};
use crate::classes::FileAccess;
use crate::global::Error;
use crate::obj::Gd;
use crate::tools::IoError;

use crate::engine::IoError;
use std::cmp;
use std::io::{BufRead, ErrorKind, Read, Seek, SeekFrom, Write};

Expand Down
2 changes: 0 additions & 2 deletions godot-core/src/tools/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@
//! or better integrated with Rust.

mod gfile;
mod io_error;
mod save_load;
mod translate;

pub use gfile::*;
pub use io_error::*;
pub use save_load::*;
pub use translate::*;
2 changes: 1 addition & 1 deletion godot-core/src/tools/save_load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

use crate::builtin::GString;
use crate::classes::{Resource, ResourceLoader, ResourceSaver};
use crate::engine::IoError;
use crate::global::Error as GodotError;
use crate::obj::{Gd, Inherits};
use crate::tools::IoError;

/// ⚠️ Loads a resource from the filesystem located at `path`, panicking on error.
///
Expand Down
5 changes: 3 additions & 2 deletions godot/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ pub use super::register::{godot_api, Export, GodotClass, GodotConvert, Var};

pub use super::builtin::__prelude_reexport::*;
pub use super::builtin::math::FloatExt as _;
pub use super::meta::{FromGodot, ToGodot};
pub use super::meta::error::{ConvertError, IoError};
pub use super::meta::{FromGodot, GodotConvert, ToGodot};

pub use super::classes::{
AudioStreamPlayer, Camera2D, Camera3D, IAudioStreamPlayer, ICamera2D, ICamera3D, INode,
Expand All @@ -22,7 +23,7 @@ pub use super::classes::{
pub use super::global::{
godot_error, godot_print, godot_print_rich, godot_script_error, godot_warn,
};
pub use super::tools::{load, save, try_load, try_save, GFile, IoError};
pub use super::tools::{load, save, try_load, try_save, GFile};

pub use super::init::{gdextension, ExtensionLibrary, InitLevel};
pub use super::obj::{Base, Gd, GdMut, GdRef, GodotClass, Inherits, InstanceId, OnReady};
Expand Down
24 changes: 13 additions & 11 deletions itest/rust/src/builtin_tests/containers/dictionary_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ fn dictionary_clone() {

#[allow(clippy::redundant_clone)]
let clone = dictionary.clone();
Dictionary::from_variant(&clone.get("bar").unwrap()).insert("final", 4);
Dictionary::from_variant(&clone.get("bar").unwrap()).set("final", 4);
assert_eq!(subdictionary.get("final"), Some(4.to_variant()));
}

Expand Down Expand Up @@ -147,7 +147,7 @@ fn dictionary_duplicate_deep() {
"bar": subdictionary.clone()
};
let clone = dictionary.duplicate_deep();
Dictionary::from_variant(&clone.get("bar").unwrap()).insert("baz", 4);
Dictionary::from_variant(&clone.get("bar").unwrap()).set("baz", 4);
assert_eq!(
subdictionary.get("baz"),
Some(true.to_variant()),
Expand All @@ -167,14 +167,14 @@ fn dictionary_duplicate_shallow() {
};

let mut clone = dictionary.duplicate_shallow();
Dictionary::from_variant(&clone.get("bar").unwrap()).insert("baz", 4);
Dictionary::from_variant(&clone.get("bar").unwrap()).set("baz", 4);
assert_eq!(
subdictionary.get("baz"),
Some(4.to_variant()),
"key = \"baz\""
);

clone.insert("foo", false.to_variant());
clone.set("foo", false);
assert_eq!(dictionary.get("foo"), Some(0.to_variant()));
assert_eq!(clone.get("foo"), Some(false.to_variant()));
}
Expand Down Expand Up @@ -256,13 +256,13 @@ fn dictionary_insert_multiple() {
let mut dictionary = dict! {};
assert!(dictionary.is_empty());

dictionary.insert(1, true);
dictionary.set(1, true);
assert_eq!(dictionary.get(1), Some(true.to_variant()));

let mut other = dict! {};
assert!(other.is_empty());

other.insert(1, 2);
other.set(1, 2);
assert_eq!(other.get(1), Some(2.to_variant()));
}
#[itest]
Expand Down Expand Up @@ -430,7 +430,7 @@ fn dictionary_iter_size_hint() {
assert_eq!(iter.size_hint(), (0, Some(0)));

// Insertion while iterating is allowed and might change size hint.
dictionary_clone.insert("new_key", "soma_val");
dictionary_clone.set("new_key", "soma_val");
assert_eq!(iter.size_hint(), (1, Some(1)));

// Removal while iterating is also allowed and might change size_hint.
Expand Down Expand Up @@ -465,7 +465,9 @@ fn dictionary_iter_insert() {
iter.next();
iter.next();

dictionary2.insert("new_key", 10);
let prev = dictionary2.insert("new_key", 10);
assert_eq!(prev, None);

let v: Vec<_> = iter.collect();
assert_eq!(dictionary.len(), 5);
assert!(dictionary.contains_key("new_key"));
Expand All @@ -488,7 +490,7 @@ fn dictionary_iter_insert_after_completion() {
}
assert_eq!(iter.next(), None);

dictionary2.insert("new_key", 10);
dictionary2.set("new_key", 10);
assert_eq!(iter.next(), None);
assert_eq!(dictionary.len(), 5);
}
Expand All @@ -504,7 +506,7 @@ fn dictionary_iter_big() {
for _ in 0..16 {
iter.next();
}
dictionary2.insert("a", "b");
dictionary2.set("a", "b");
}
dictionary2.clear();
dictionary2.extend((0..64).zip(0..64));
Expand All @@ -531,7 +533,7 @@ fn dictionary_iter_simultaneous() {
})
.collect();

assert!(map.len() == 4);
assert_eq!(map.len(), 4);

let mut tens = 0;
let mut trues = 0;
Expand Down