Skip to content

Commit

Permalink
Merge pull request #795 from Houtamelo/master
Browse files Browse the repository at this point in the history
Implement `GodotConvert` for `Vec<T>`, `[T; N]` and `&[T]`
  • Loading branch information
Bromeon authored Aug 12, 2024
2 parents 77500ba + 7de3d38 commit 6bcaa3c
Show file tree
Hide file tree
Showing 15 changed files with 162 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/full-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ jobs:

- name: linux
os: ubuntu-20.04
rust-toolchain: "1.78"
rust-toolchain: "1.80"
rust-special: -msrv

steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/update-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ on:

env:
# Keep this a variable for easy search&replace.
MSRV: 1.78
MSRV: 1.80

jobs:
notify-docs:
Expand Down
2 changes: 1 addition & 1 deletion examples/dodge-the-creeps/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "dodge-the-creeps"
version = "0.1.0"
edition = "2021"
rust-version = "1.78"
rust-version = "1.80"
license = "MPL-2.0"
publish = false

Expand Down
2 changes: 1 addition & 1 deletion godot-bindings/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "godot-bindings"
version = "0.1.3"
edition = "2021"
rust-version = "1.78"
rust-version = "1.80"
license = "MPL-2.0"
keywords = ["gamedev", "godot", "engine", "ffi", "sys"]
categories = ["game-engines", "graphics"]
Expand Down
2 changes: 1 addition & 1 deletion godot-cell/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "godot-cell"
version = "0.1.3"
edition = "2021"
rust-version = "1.78"
rust-version = "1.80"
license = "MPL-2.0"
keywords = ["gamedev", "godot", "engine", "ffi"]
categories = ["game-engines", "graphics"]
Expand Down
2 changes: 1 addition & 1 deletion godot-codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "godot-codegen"
version = "0.1.3"
edition = "2021"
rust-version = "1.78"
rust-version = "1.80"
license = "MPL-2.0"
keywords = ["gamedev", "godot", "engine", "codegen"]
categories = ["game-engines", "graphics"]
Expand Down
2 changes: 1 addition & 1 deletion godot-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "godot-core"
version = "0.1.3"
edition = "2021"
rust-version = "1.78"
rust-version = "1.80"
license = "MPL-2.0"
keywords = ["gamedev", "godot", "engine", "2d", "3d"] # possibly: "ffi"
categories = ["game-engines", "graphics"]
Expand Down
69 changes: 68 additions & 1 deletion godot-core/src/meta/godot_convert/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

use crate::builtin::{Array, Variant};
use crate::meta::error::{ConvertError, FromFfiError, FromVariantError};
use crate::meta::error::{ConvertError, ErrorKind, FromFfiError, FromVariantError};
use crate::meta::{
ArrayElement, ClassName, FromGodot, GodotConvert, GodotNullableFfi, GodotType,
PropertyHintInfo, PropertyInfo, ToGodot,
Expand Down Expand Up @@ -338,6 +338,73 @@ impl FromGodot for u64 {
}
}

// ----------------------------------------------------------------------------------------------------------------------------------------------
// Collections

impl<T: ArrayElement> GodotConvert for Vec<T> {
type Via = Array<T>;
}

impl<T: ArrayElement> ToGodot for Vec<T> {
fn to_godot(&self) -> Self::Via {
Array::from(self.as_slice())
}
}

impl<T: ArrayElement> FromGodot for Vec<T> {
fn try_from_godot(via: Self::Via) -> Result<Self, ConvertError> {
Ok(via.iter_shared().collect())
}
}

impl<T: ArrayElement, const LEN: usize> GodotConvert for [T; LEN] {
type Via = Array<T>;
}

impl<T: ArrayElement, const LEN: usize> ToGodot for [T; LEN] {
fn to_godot(&self) -> Self::Via {
Array::from(self)
}
}

impl<T: ArrayElement, const LEN: usize> FromGodot for [T; LEN] {
fn try_from_godot(via: Self::Via) -> Result<Self, ConvertError> {
let via_len = via.len(); // Caching this avoids an FFI call
if via_len != LEN {
let message =
format!("Array<T> of length {via_len} cannot be stored in [T; {LEN}] Rust array");
return Err(ConvertError::with_kind_value(
ErrorKind::Custom(Some(message.into())),
via,
));
}

let mut option_array = [const { None }; LEN];

for (element, destination) in via.iter_shared().zip(&mut option_array) {
*destination = Some(element);
}

let array = option_array.map(|some| {
some.expect(
"Elements were removed from Array during `iter_shared()`, this is not allowed",
)
});

Ok(array)
}
}

impl<T: ArrayElement> GodotConvert for &[T] {
type Via = Array<T>;
}

impl<T: ArrayElement> ToGodot for &[T] {
fn to_godot(&self) -> Self::Via {
Array::from(*self)
}
}

// ----------------------------------------------------------------------------------------------------------------------------------------------
// Raw pointers

Expand Down
6 changes: 1 addition & 5 deletions godot-core/src/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,7 @@ struct CallErrors {
impl Default for CallErrors {
fn default() -> Self {
Self {
// [None; N] requires Clone. The following is possible once MSRV lifts to 1.79:
// ring_buffer: [const { None }; Self::MAX_ENTRIES as usize].into(),
ring_buffer: std::iter::repeat_with(|| None)
.take(Self::MAX_ENTRIES as usize)
.collect(),
ring_buffer: [const { None }; Self::MAX_ENTRIES as usize].into(),
next_id: 0,
generation: 0,
}
Expand Down
2 changes: 1 addition & 1 deletion godot-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "godot-ffi"
version = "0.1.3"
edition = "2021"
rust-version = "1.78"
rust-version = "1.80"
license = "MPL-2.0"
keywords = ["gamedev", "godot", "engine", "ffi"]
categories = ["game-engines", "graphics"]
Expand Down
2 changes: 1 addition & 1 deletion godot-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "godot-macros"
version = "0.1.3"
edition = "2021"
rust-version = "1.78"
rust-version = "1.80"
license = "MPL-2.0"
keywords = ["gamedev", "godot", "engine", "derive", "macro"]
categories = ["game-engines", "graphics"]
Expand Down
2 changes: 1 addition & 1 deletion godot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "godot"
version = "0.1.3"
edition = "2021"
rust-version = "1.78"
rust-version = "1.80"
license = "MPL-2.0"
keywords = ["gamedev", "godot", "engine", "2d", "3d"] # possibly: "ffi"
categories = ["game-engines", "graphics"]
Expand Down
2 changes: 1 addition & 1 deletion itest/repo-tweak/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "repo-tweak"
version = "0.1.0"
edition = "2021"
rust-version = "1.78"
rust-version = "1.80"
license = "MPL-2.0"
publish = false

Expand Down
2 changes: 1 addition & 1 deletion itest/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "itest"
version = "0.0.0"
edition = "2021"
rust-version = "1.78"
rust-version = "1.80"
license = "MPL-2.0"
publish = false

Expand Down
82 changes: 81 additions & 1 deletion itest/rust/src/builtin_tests/convert_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

use godot::builtin::{
dict, Array, Dictionary, GString, Variant, VariantArray, Vector2, Vector2Axis,
array, dict, Array, Dictionary, GString, Variant, VariantArray, Vector2, Vector2Axis,
};
use godot::classes::{Node, Resource};
use godot::meta::error::ConvertError;
Expand Down Expand Up @@ -233,3 +233,83 @@ fn custom_convert_error_from_variant() {
format!("{:?}", i64::MAX)
);
}

#[itest]
fn vec_to_array() {
let from = vec![1, 2, 3];
let to = from.to_variant().to::<Array<i32>>();
assert_eq!(to, array![1, 2, 3]);

let from = vec![GString::from("Hello"), GString::from("World")];
let to = from.to_variant().to::<Array<GString>>();
assert_eq!(to, array![GString::from("Hello"), GString::from("World")]);

// Invalid conversion.
let from = vec![1, 2, 3];
let to = from.to_variant().try_to::<Array<f32>>();
assert!(to.is_err());
}

#[itest]
fn array_to_vec() {
let from = array![1, 2, 3];
let to = from.to_variant().to::<Vec<i32>>();
assert_eq!(to, vec![1, 2, 3]);

let from = array![GString::from("Hello"), GString::from("World")];
let to = from.to_variant().to::<Vec<GString>>();
assert_eq!(to, vec![GString::from("Hello"), GString::from("World")]);

// Invalid conversion.
let from = array![1, 2, 3];
let to = from.to_variant().try_to::<Vec<f32>>();
assert!(to.is_err());
}

#[itest]
fn rust_array_to_array() {
let from = [1, 2, 3];
let to = from.to_variant().to::<Array<i32>>();
assert_eq!(to, array![1, 2, 3]);

let from = [GString::from("Hello"), GString::from("World")];
let to = from.to_variant().to::<Array<GString>>();
assert_eq!(to, array![GString::from("Hello"), GString::from("World")]);

// Invalid conversion.
let from = [1, 2, 3];
let to = from.to_variant().try_to::<Array<f32>>();
assert!(to.is_err());
}

#[itest]
fn array_to_rust_array() {
let from = array![1, 2, 3];
let to = from.to_variant().to::<[i32; 3]>();
assert_eq!(to, [1, 2, 3]);

let from = array![GString::from("Hello"), GString::from("World")];
let to = from.to_variant().to::<[GString; 2]>();
assert_eq!(to, [GString::from("Hello"), GString::from("World")]);

// Invalid conversion.
let from = array![1, 2, 3];
let to = from.to_variant().try_to::<[f32; 3]>();
assert!(to.is_err());
}

#[itest]
fn slice_to_array() {
let from = &[1, 2, 3];
let to = from.to_variant().to::<Array<i32>>();
assert_eq!(to, array![1, 2, 3]);

let from = &[GString::from("Hello"), GString::from("World")];
let to = from.to_variant().to::<Array<GString>>();
assert_eq!(to, array![GString::from("Hello"), GString::from("World")]);

// Invalid conversion.
let from = &[1, 2, 3];
let to = from.to_variant().try_to::<Array<f32>>();
assert!(to.is_err());
}

0 comments on commit 6bcaa3c

Please sign in to comment.