Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
693: Add the MapOwned trait and the `Once<T>` userdata type r=toasteater a=toasteater This adds support for exporting methods that take ownership of `self`. `Once<T>` is a userdata wrapper that uses atomic compare-exchange to allow taking ownership safely once. 700: Add into_inner method to ArcData r=toasteater a=Waridley As discussed in Discord, this method is especially useful for coercing the `script` of an `Instance` into a trait object, thus being able to benefit from more Rust conveniences within Godot scripts. This *could* be written as an `impl<T> Into<Arc<T>> for ArcData<T>`, but I feel like this makes it more clear that it's not expected for the user to be able to freely treat `ArcData` as an `Arc` whenever they want to, but rather must be explicit about accessing the internals of this type -- even if it should theoretically be as memory-safe as using the `ArcData` anyway. I decided to have this method take ownership of `self` because if you have reference to an `ArcData`, you should still be able to call `clone()` on it to get an owned copy, but the opposite would not be as easy if the user didn't want to increment the ref count. Co-authored-by: toasteater <48371905+toasteater@users.noreply.github.com> Co-authored-by: Waridley <Waridley64@gmail.com>
- Loading branch information
Showing
7 changed files
with
287 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
use gdnative::nativescript::user_data::Once; | ||
use gdnative::prelude::*; | ||
|
||
pub(crate) fn run_tests() -> bool { | ||
let mut status = true; | ||
|
||
status &= test_map_owned(); | ||
|
||
status | ||
} | ||
|
||
pub(crate) fn register(handle: InitHandle) { | ||
handle.add_class::<VecBuilder>(); | ||
} | ||
|
||
#[derive(NativeClass)] | ||
#[no_constructor] | ||
#[inherit(Reference)] | ||
#[user_data(Once<Self>)] | ||
struct VecBuilder { | ||
v: Vec<i32>, | ||
} | ||
|
||
#[methods] | ||
impl VecBuilder { | ||
#[export] | ||
fn append(mut self, _owner: TRef<Reference>, mut numbers: Vec<i32>) -> Instance<Self, Shared> { | ||
self.v.append(&mut numbers); | ||
Instance::emplace(Self { v: self.v }).into_shared() | ||
} | ||
} | ||
|
||
fn test_map_owned() -> bool { | ||
println!(" -- test_map_owned"); | ||
|
||
let ok = std::panic::catch_unwind(|| { | ||
let v1 = Instance::emplace(VecBuilder { v: Vec::new() }).into_shared(); | ||
let v1 = unsafe { v1.assume_safe() }; | ||
|
||
let v2 = v1 | ||
.map_owned(|s, owner| s.append(owner, vec![1, 2, 3])) | ||
.unwrap(); | ||
let v2 = unsafe { v2.assume_safe() }; | ||
assert!(v1 | ||
.map_owned(|_, _| panic!("should never be called")) | ||
.is_err()); | ||
|
||
let v3 = v2 | ||
.map_owned(|s, owner| s.append(owner, vec![4, 5, 6])) | ||
.unwrap(); | ||
let v3 = unsafe { v3.assume_safe() }; | ||
assert!(v2 | ||
.map_owned(|_, _| panic!("should never be called")) | ||
.is_err()); | ||
|
||
let v = v3.map_owned(|s, _| s.v).unwrap(); | ||
assert_eq!(&v, &[1, 2, 3, 4, 5, 6]); | ||
assert!(v3 | ||
.map_owned(|_, _| panic!("should never be called")) | ||
.is_err()); | ||
}) | ||
.is_ok(); | ||
|
||
if !ok { | ||
gdnative::godot_error!(" !! Test test_map_owned failed"); | ||
} | ||
|
||
ok | ||
} |