Skip to content

Commit beee6ff

Browse files
committed
godot_core::engine::io module
1 parent 0b93fe1 commit beee6ff

File tree

7 files changed

+199
-177
lines changed

7 files changed

+199
-177
lines changed

godot-core/src/engine/gfile.rs renamed to godot-core/src/engine/io/gfile.rs

Lines changed: 1 addition & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@ use crate::builtin::{real, GString, PackedByteArray, PackedStringArray, Variant}
99
use crate::engine::file_access::{CompressionMode, ModeFlags};
1010
use crate::gen::central::global::Error;
1111
use crate::gen::classes::FileAccess;
12-
use crate::obj::{Gd, Inherits};
12+
use crate::obj::{Gd, NotUniqueError};
1313

1414
use std::cmp;
1515
use std::io::{
1616
BufRead, Error as IoError, ErrorKind, Read, Result as IoResult, Seek, SeekFrom, Write,
1717
};
1818

19-
use super::RefCounted;
20-
2119
/// Open a file for reading or writing.
2220
///
2321
/// This is a convenient wrapper around a [`FileAccess`] pointer with a unique reference, providing both safety and
@@ -832,85 +830,3 @@ impl BufRead for GFile {
832830
self.seek(pos).expect("failed to consume bytes during read");
833831
}
834832
}
835-
836-
// ----------------------------------------------------------------------------------------------------------------------------------------------
837-
// Errors.
838-
839-
/// Error stemming from the non-uniqueness of the [`Gd`] instance.
840-
///
841-
/// Keeping track of the uniqueness of references can be crucial in many applications, especially if we want to ensure
842-
/// that the passed [`Gd`] reference will be possessed by only one different object instance or function in its lifetime.
843-
///
844-
/// Only applicable to [`GodotClass`](crate::obj::GodotClass) objects that inherit from [`RefCounted`]. To check the
845-
/// uniqueness, call the `check()` associated method.
846-
///
847-
/// ## Example
848-
///
849-
/// ```no_run
850-
/// use godot::engine::RefCounted;
851-
/// use godot::engine::NotUniqueError;
852-
///
853-
/// let shared = RefCounted::new();
854-
/// let cloned = shared.clone();
855-
/// let result = NotUniqueError::check(shared);
856-
///
857-
/// assert!(result.is_err());
858-
///
859-
/// if let Err(error) = result {
860-
/// assert_eq!(error.get_reference_count(), 2)
861-
/// }
862-
/// ```
863-
#[derive(Debug)]
864-
pub struct NotUniqueError {
865-
reference_count: i32,
866-
}
867-
868-
impl NotUniqueError {
869-
/// check [`Gd`] reference uniqueness.
870-
///
871-
/// Checks the [`Gd`] of the [`GodotClass`](crate::obj::GodotClass) that inherits from [`RefCounted`] if it is unique
872-
/// reference to the object.
873-
///
874-
/// ## Example
875-
///
876-
/// ```no_run
877-
/// use godot::engine::RefCounted;
878-
/// use godot::engine::NotUniqueError;
879-
///
880-
/// let unique = RefCounted::new();
881-
/// assert!(NotUniqueError::check(unique).is_ok());
882-
///
883-
/// let shared = RefCounted::new();
884-
/// let cloned = shared.clone();
885-
/// assert!(NotUniqueError::check(shared).is_err());
886-
/// assert!(NotUniqueError::check(cloned).is_err());
887-
/// ```
888-
pub fn check<T>(rc: Gd<T>) -> Result<Gd<T>, Self>
889-
where
890-
T: Inherits<RefCounted>,
891-
{
892-
let rc = rc.upcast::<RefCounted>();
893-
let reference_count = rc.get_reference_count();
894-
895-
if reference_count != 1 {
896-
Err(Self { reference_count })
897-
} else {
898-
Ok(rc.cast::<T>())
899-
}
900-
}
901-
902-
/// Get the detected reference count
903-
pub fn get_reference_count(&self) -> i32 {
904-
self.reference_count
905-
}
906-
}
907-
908-
impl std::fmt::Display for NotUniqueError {
909-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
910-
write!(
911-
f,
912-
"pointer is not unique, current reference count: {}",
913-
self.reference_count
914-
)
915-
}
916-
}

godot-core/src/engine/io/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright (c) godot-rust; Bromeon and contributors.
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
mod gfile;
9+
mod resources;
10+
11+
pub use gfile::GFile;
12+
pub use resources::{load, try_load};

godot-core/src/engine/io/resources.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright (c) godot-rust; Bromeon and contributors.
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
use crate::builtin::GString;
9+
use crate::gen::classes::{Resource, ResourceLoader};
10+
use crate::obj::{Gd, GodotClass, Inherits};
11+
12+
/// Loads a resource from the filesystem located at `path`, panicking on error.
13+
///
14+
/// See [`try_load`] for more information.
15+
///
16+
/// # Example
17+
///
18+
/// ```no_run
19+
/// use godot::prelude::*;
20+
///
21+
/// let scene = load::<PackedScene>("res://path/to/Main.tscn");
22+
/// ```
23+
///
24+
/// # Panics
25+
/// If the resource cannot be loaded, or is not of type `T` or inherited.
26+
#[inline]
27+
pub fn load<T>(path: impl Into<GString>) -> Gd<T>
28+
where
29+
T: GodotClass + Inherits<Resource>,
30+
{
31+
let path = path.into();
32+
load_impl(&path).unwrap_or_else(|| panic!("failed to load node at path `{path}`"))
33+
}
34+
35+
/// Loads a resource from the filesystem located at `path`.
36+
///
37+
/// The resource is loaded on the method call (unless it's referenced already elsewhere, e.g. in another script or in the scene),
38+
/// which might cause slight delay, especially when loading scenes.
39+
///
40+
/// If the resource cannot be loaded, or is not of type `T` or inherited, this method returns `None`.
41+
///
42+
/// This method is a simplified version of [`ResourceLoader::load()`][crate::engine::ResourceLoader::load],
43+
/// which can be used for more advanced scenarios.
44+
///
45+
/// # Note:
46+
/// Resource paths can be obtained by right-clicking on a resource in the Godot editor (_FileSystem_ dock) and choosing "Copy Path",
47+
/// or by dragging the file from the _FileSystem_ dock into the script.
48+
///
49+
/// The path must be absolute (typically starting with `res://`), a local path will fail.
50+
///
51+
/// # Example
52+
/// Loads a scene called `Main` located in the `path/to` subdirectory of the Godot project and caches it in a variable.
53+
/// The resource is directly stored with type `PackedScene`.
54+
///
55+
/// ```no_run
56+
/// use godot::prelude::*;
57+
///
58+
/// if let Some(scene) = try_load::<PackedScene>("res://path/to/Main.tscn") {
59+
/// // all good
60+
/// } else {
61+
/// // handle error
62+
/// }
63+
/// ```
64+
// TODO Result to differentiate 2 errors
65+
#[inline]
66+
pub fn try_load<T>(path: impl Into<GString>) -> Option<Gd<T>>
67+
where
68+
T: GodotClass + Inherits<Resource>,
69+
{
70+
load_impl(&path.into())
71+
}
72+
73+
// ----------------------------------------------------------------------------------------------------------------------------------------------
74+
// Implementation of this file
75+
76+
// Separate function, to avoid constructing string twice
77+
// Note that more optimizations than that likely make no sense, as loading is quite expensive
78+
fn load_impl<T>(path: &GString) -> Option<Gd<T>>
79+
where
80+
T: GodotClass + Inherits<Resource>,
81+
{
82+
ResourceLoader::singleton()
83+
.load_ex(path.clone())
84+
.type_hint(T::class_name().to_godot_string())
85+
.done() // TODO unclone
86+
.and_then(|res| res.try_cast::<T>().ok())
87+
}

godot-core/src/engine/mod.rs

Lines changed: 2 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ pub use crate::gen::utilities;
1919

2020
use crate::sys;
2121

22-
mod gfile;
22+
mod io;
2323
mod script_instance;
2424

25-
pub use gfile::{GFile, NotUniqueError};
25+
pub use io::*;
2626
pub use script_instance::{create_script_instance, ScriptInstance};
2727

2828
#[cfg(debug_assertions)]
@@ -132,67 +132,6 @@ where
132132
}
133133
}
134134

135-
/// Loads a resource from the filesystem located at `path`, panicking on error.
136-
///
137-
/// See [`try_load`] for more information.
138-
///
139-
/// # Example
140-
///
141-
/// ```no_run
142-
/// use godot::prelude::*;
143-
///
144-
/// let scene = load::<PackedScene>("res://path/to/Main.tscn");
145-
/// ```
146-
///
147-
/// # Panics
148-
/// If the resource cannot be loaded, or is not of type `T` or inherited.
149-
#[inline]
150-
pub fn load<T>(path: impl Into<GString>) -> Gd<T>
151-
where
152-
T: GodotClass + Inherits<Resource>,
153-
{
154-
let path = path.into();
155-
load_impl(&path).unwrap_or_else(|| panic!("failed to load node at path `{path}`"))
156-
}
157-
158-
/// Loads a resource from the filesystem located at `path`.
159-
///
160-
/// The resource is loaded on the method call (unless it's referenced already elsewhere, e.g. in another script or in the scene),
161-
/// which might cause slight delay, especially when loading scenes.
162-
///
163-
/// If the resource cannot be loaded, or is not of type `T` or inherited, this method returns `None`.
164-
///
165-
/// This method is a simplified version of [`ResourceLoader::load()`][crate::engine::ResourceLoader::load],
166-
/// which can be used for more advanced scenarios.
167-
///
168-
/// # Note:
169-
/// Resource paths can be obtained by right-clicking on a resource in the Godot editor (_FileSystem_ dock) and choosing "Copy Path",
170-
/// or by dragging the file from the _FileSystem_ dock into the script.
171-
///
172-
/// The path must be absolute (typically starting with `res://`), a local path will fail.
173-
///
174-
/// # Example
175-
/// Loads a scene called `Main` located in the `path/to` subdirectory of the Godot project and caches it in a variable.
176-
/// The resource is directly stored with type `PackedScene`.
177-
///
178-
/// ```no_run
179-
/// use godot::prelude::*;
180-
///
181-
/// if let Some(scene) = try_load::<PackedScene>("res://path/to/Main.tscn") {
182-
/// // all good
183-
/// } else {
184-
/// // handle error
185-
/// }
186-
/// ```
187-
// TODO Result to differentiate 2 errors
188-
#[inline]
189-
pub fn try_load<T>(path: impl Into<GString>) -> Option<Gd<T>>
190-
where
191-
T: GodotClass + Inherits<Resource>,
192-
{
193-
load_impl(&path.into())
194-
}
195-
196135
// ----------------------------------------------------------------------------------------------------------------------------------------------
197136
// Utilities for crate
198137

@@ -287,16 +226,3 @@ fn is_derived_base_cached(derived: ClassName, base: ClassName) -> bool {
287226

288227
is_parent_class
289228
}
290-
291-
// Separate function, to avoid constructing string twice
292-
// Note that more optimizations than that likely make no sense, as loading is quite expensive
293-
fn load_impl<T>(path: &GString) -> Option<Gd<T>>
294-
where
295-
T: GodotClass + Inherits<Resource>,
296-
{
297-
ResourceLoader::singleton()
298-
.load_ex(path.clone())
299-
.type_hint(T::class_name().to_gstring())
300-
.done() // TODO unclone
301-
.and_then(|res| res.try_cast::<T>().ok())
302-
}

godot-core/src/obj/gd.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,3 +692,82 @@ impl<T: GodotClass> std::hash::Hash for Gd<T> {
692692
// its mutability is anyway present, in the Godot engine.
693693
impl<T: GodotClass> std::panic::UnwindSafe for Gd<T> {}
694694
impl<T: GodotClass> std::panic::RefUnwindSafe for Gd<T> {}
695+
696+
/// Error stemming from the non-uniqueness of the [`Gd`] instance.
697+
///
698+
/// Keeping track of the uniqueness of references can be crucial in many applications, especially if we want to ensure
699+
/// that the passed [`Gd`] reference will be possessed by only one different object instance or function in its lifetime.
700+
///
701+
/// Only applicable to [`GodotClass`] objects that inherit from [`RefCounted`](crate::gen::classes::RefCounted). To check the
702+
/// uniqueness, call the `check()` associated method.
703+
///
704+
/// ## Example
705+
///
706+
/// ```no_run
707+
/// use godot::engine::RefCounted;
708+
/// use godot::obj::NotUniqueError;
709+
///
710+
/// let shared = RefCounted::new();
711+
/// let cloned = shared.clone();
712+
/// let result = NotUniqueError::check(shared);
713+
///
714+
/// assert!(result.is_err());
715+
///
716+
/// if let Err(error) = result {
717+
/// assert_eq!(error.get_reference_count(), 2)
718+
/// }
719+
/// ```
720+
#[derive(Debug)]
721+
pub struct NotUniqueError {
722+
reference_count: i32,
723+
}
724+
725+
impl NotUniqueError {
726+
/// check [`Gd`] reference uniqueness.
727+
///
728+
/// Checks the [`Gd`] of the [`GodotClass`](crate::obj::GodotClass) that inherits from [`RefCounted`](crate::gen::classes::RefCounted)
729+
/// if it is an unique reference to the object.
730+
///
731+
/// ## Example
732+
///
733+
/// ```no_run
734+
/// use godot::engine::RefCounted;
735+
/// use godot::obj::NotUniqueError;
736+
///
737+
/// let unique = RefCounted::new();
738+
/// assert!(NotUniqueError::check(unique).is_ok());
739+
///
740+
/// let shared = RefCounted::new();
741+
/// let cloned = shared.clone();
742+
/// assert!(NotUniqueError::check(shared).is_err());
743+
/// assert!(NotUniqueError::check(cloned).is_err());
744+
/// ```
745+
pub fn check<T>(rc: Gd<T>) -> Result<Gd<T>, Self>
746+
where
747+
T: Inherits<crate::gen::classes::RefCounted>,
748+
{
749+
let rc = rc.upcast::<crate::gen::classes::RefCounted>();
750+
let reference_count = rc.get_reference_count();
751+
752+
if reference_count != 1 {
753+
Err(Self { reference_count })
754+
} else {
755+
Ok(rc.cast::<T>())
756+
}
757+
}
758+
759+
/// Get the detected reference count
760+
pub fn get_reference_count(&self) -> i32 {
761+
self.reference_count
762+
}
763+
}
764+
765+
impl std::fmt::Display for NotUniqueError {
766+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
767+
write!(
768+
f,
769+
"pointer is not unique, current reference count: {}",
770+
self.reference_count
771+
)
772+
}
773+
}

0 commit comments

Comments
 (0)