@@ -9,6 +9,13 @@ use crate::core_types::{Color, GodotString, VariantArray, Vector2, Vector3};
9
9
use crate :: object:: NewRef ;
10
10
use crate :: private:: get_api;
11
11
12
+ /// A RAII read access for Godot pool arrays.
13
+ pub type Read < ' a , T > = Aligned < ReadGuard < ' a , T > > ;
14
+
15
+ /// A RAII write access for Godot pool arrays. This will only lock the CoW container once,
16
+ /// as opposed to every time with methods like `push()`.
17
+ pub type Write < ' a , T > = Aligned < WriteGuard < ' a , T > > ;
18
+
12
19
/// A reference-counted CoW typed vector using Godot's pool allocator, generic over possible
13
20
/// element types.
14
21
///
@@ -19,65 +26,21 @@ use crate::private::get_api;
19
26
/// If you need other types, look into [`VariantArray`](struct.VariantArray.html) or directly use
20
27
/// `Vec<T>` for type safety.
21
28
///
22
- /// This type is CoW. The `Clone` implementation of this type creates a new reference without
23
- /// copying the contents.
29
+ /// This type is CoW (copy-on-write) . The `Clone` implementation of this type creates a new
30
+ /// reference without copying the contents.
24
31
///
25
- /// When using this type, it's generally better to perform mutations in batch using `write`,
26
- /// or the `append` methods, as opposed to `push` or `set`, because the latter ones trigger
32
+ /// If you need to read elements, e.g. for iteration or conversion to another collection,
33
+ /// the [`read()`][Self::read] method provides a view that dereferences to `&[T]`.
34
+ /// Analogously, [`write()`][Self::write] provides a writable view that dereferences to `&mut [T]`.
35
+ ///
36
+ /// For element mutations, it's usually recommended to do process them in batch using
37
+ /// [`write()`][Self::write] or the [`append()`][Self::append] methods, as opposed to
38
+ /// [`push()`][Self::push] or [`set()`][Self::set], because the latter ones trigger
27
39
/// CoW behavior each time they are called.
28
40
pub struct PoolArray < T : PoolElement > {
29
41
inner : T :: SysArray ,
30
42
}
31
43
32
- /// A RAII read access for Godot typed arrays.
33
- pub type Read < ' a , T > = Aligned < ReadGuard < ' a , T > > ;
34
-
35
- /// A RAII write access for Godot typed arrays. This will only lock the CoW container once,
36
- /// as opposed to every time with methods like `push`.
37
- pub type Write < ' a , T > = Aligned < WriteGuard < ' a , T > > ;
38
-
39
- impl < T : PoolElement > Drop for PoolArray < T > {
40
- #[ inline]
41
- fn drop ( & mut self ) {
42
- unsafe {
43
- ( T :: destroy_fn ( get_api ( ) ) ) ( self . sys_mut ( ) ) ;
44
- }
45
- }
46
- }
47
-
48
- impl < T : PoolElement > Default for PoolArray < T > {
49
- #[ inline]
50
- fn default ( ) -> Self {
51
- PoolArray :: new ( )
52
- }
53
- }
54
-
55
- impl < T : PoolElement + fmt:: Debug > fmt:: Debug for PoolArray < T > {
56
- #[ inline]
57
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
58
- f. debug_list ( ) . entries ( self . read ( ) . iter ( ) ) . finish ( )
59
- }
60
- }
61
-
62
- impl < T : PoolElement > Clone for PoolArray < T > {
63
- #[ inline]
64
- fn clone ( & self ) -> Self {
65
- self . new_ref ( )
66
- }
67
- }
68
-
69
- impl < T : PoolElement > NewRef for PoolArray < T > {
70
- /// Creates a new reference to this reference-counted instance.
71
- #[ inline]
72
- fn new_ref ( & self ) -> Self {
73
- unsafe {
74
- let mut inner = T :: SysArray :: default ( ) ;
75
- ( T :: new_copy_fn ( get_api ( ) ) ) ( & mut inner, self . sys ( ) ) ;
76
- PoolArray { inner }
77
- }
78
- }
79
- }
80
-
81
44
impl < T : PoolElement > PoolArray < T > {
82
45
/// Creates an empty array.
83
46
#[ inline]
@@ -100,26 +63,56 @@ impl<T: PoolElement> PoolArray<T> {
100
63
}
101
64
102
65
/// Creates a `PoolArray` moving elements from `src`.
66
+ ///
67
+ /// If your source type isn't precisely a `Vec<T>`, keep in mind that `PoolElement` implements the
68
+ /// `FromIterator` trait, which allows it to be constructed from iterators, typically through `collect()`.
69
+ ///
70
+ /// For example:
71
+ /// ```no_run
72
+ /// // Int32Array is a type alias for PoolArray<i32>
73
+ /// use gdnative::core_types::Int32Array;
74
+ ///
75
+ /// // Collect from range
76
+ /// let arr = (0..4).collect::<Int32Array>();
77
+ ///
78
+ /// // Type conversion
79
+ /// let vec: Vec<u32> = vec![1, 1, 2, 3, 5]; // note: unsigned
80
+ /// let arr = vec.iter().map(|&e| e as i32).collect::<Int32Array>();
81
+ /// ```
103
82
#[ inline]
104
83
pub fn from_vec ( mut src : Vec < T > ) -> Self {
105
84
let mut arr = Self :: new ( ) ;
106
85
arr. append_vec ( & mut src) ;
107
86
arr
108
87
}
109
88
89
+ /// Copies all elements to a `Vec`, leaving this instance untouched.
90
+ ///
91
+ /// Equivalent to `self.read().to_vec()`. Only use this if your destination type is precisely
92
+ /// a `Vec<T>`. Otherwise, call [`read()`][Self::read] which can be used as a slice.
93
+ ///
94
+ #[ inline]
95
+ pub fn to_vec ( & self ) -> Vec < T >
96
+ where
97
+ T : Clone ,
98
+ {
99
+ let guard = self . read ( ) ;
100
+ guard. to_vec ( )
101
+ }
102
+
110
103
/// Appends an element to the end of the array.
111
104
///
112
- /// Calling `push` triggers copy-on-write behavior. To insert a large number of elements,
113
- /// consider using ` resize` and `write` .
105
+ /// Calling `push() ` triggers copy-on-write behavior. To insert a large number of elements,
106
+ /// consider using [`append()`][Self::append], [` resize()`][Self::resize] or [ `write()`][Self::write] .
114
107
#[ inline]
115
108
pub fn push ( & mut self , val : T ) {
116
109
self . push_ref ( & val)
117
110
}
118
111
119
112
/// Appends an element to the end of the array by reference.
120
113
///
121
- /// Calling `push ` triggers copy-on-write behavior. To insert a large number of elements,
122
- /// consider using ` resize` and `write` .
114
+ /// Calling `push_ref() ` triggers copy-on-write behavior. To insert a large number of elements,
115
+ /// consider using [`append()`][Self::append], [` resize()`][Self::resize] or [ `write()`][Self::write] .
123
116
#[ inline]
124
117
pub fn push_ref ( & mut self , val : & T ) {
125
118
unsafe {
@@ -225,7 +218,10 @@ impl<T: PoolElement> PoolArray<T> {
225
218
self . len ( ) == 0
226
219
}
227
220
228
- /// Returns a RAII read access into this array.
221
+ /// Returns a scoped read-only view into this array.
222
+ ///
223
+ /// The returned read guard implements `Deref` with target type `[T]`, i.e. can be dereferenced to `&[T]`.
224
+ /// This means all non-mutating (`&self`) slice methods can be used, see [here](struct.Aligned.html#deref-methods).
229
225
#[ inline]
230
226
pub fn read ( & self ) -> Read < ' _ , T > {
231
227
unsafe {
@@ -235,8 +231,11 @@ impl<T: PoolElement> PoolArray<T> {
235
231
}
236
232
}
237
233
238
- /// Returns a RAII write access into this array. This triggers CoW once per lock, instead
234
+ /// Returns a scoped read- write view into this array. This triggers CoW once per lock, instead
239
235
/// of once each mutation.
236
+ ///
237
+ /// The returned write guard implements `DerefMut` with target type `[T]`, i.e. can be dereferenced to `&mut [T]`.
238
+ /// This means all mutating and read-only slice methods can be used, see [here](struct.Aligned.html#deref-methods).
240
239
#[ inline]
241
240
pub fn write ( & mut self ) -> Write < ' _ , T > {
242
241
unsafe {
@@ -268,6 +267,8 @@ impl<T: PoolElement> PoolArray<T> {
268
267
impl < T : PoolElement + Copy > PoolArray < T > {
269
268
/// Creates a new `PoolArray` by copying from `src`.
270
269
///
270
+ /// Equivalent to
271
+ ///
271
272
/// # Panics
272
273
///
273
274
/// If the length of `src` does not fit in `i32`.
@@ -294,6 +295,48 @@ impl<T: PoolElement + Copy> PoolArray<T> {
294
295
}
295
296
}
296
297
298
+ impl < T : PoolElement > Drop for PoolArray < T > {
299
+ #[ inline]
300
+ fn drop ( & mut self ) {
301
+ unsafe {
302
+ ( T :: destroy_fn ( get_api ( ) ) ) ( self . sys_mut ( ) ) ;
303
+ }
304
+ }
305
+ }
306
+
307
+ impl < T : PoolElement > Default for PoolArray < T > {
308
+ #[ inline]
309
+ fn default ( ) -> Self {
310
+ PoolArray :: new ( )
311
+ }
312
+ }
313
+
314
+ impl < T : PoolElement + fmt:: Debug > fmt:: Debug for PoolArray < T > {
315
+ #[ inline]
316
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
317
+ f. debug_list ( ) . entries ( self . read ( ) . iter ( ) ) . finish ( )
318
+ }
319
+ }
320
+
321
+ impl < T : PoolElement > Clone for PoolArray < T > {
322
+ #[ inline]
323
+ fn clone ( & self ) -> Self {
324
+ self . new_ref ( )
325
+ }
326
+ }
327
+
328
+ impl < T : PoolElement > NewRef for PoolArray < T > {
329
+ /// Creates a new reference to this reference-counted instance.
330
+ #[ inline]
331
+ fn new_ref ( & self ) -> Self {
332
+ unsafe {
333
+ let mut inner = T :: SysArray :: default ( ) ;
334
+ ( T :: new_copy_fn ( get_api ( ) ) ) ( & mut inner, self . sys ( ) ) ;
335
+ PoolArray { inner }
336
+ }
337
+ }
338
+ }
339
+
297
340
// `FromIterator` and `Extend` implementations collect into `Vec` first, because Rust `Vec`s
298
341
// are better at handling unknown lengths than the Godot arrays (`push` CoWs every time!)
299
342
0 commit comments