@@ -9,6 +9,13 @@ use crate::core_types::{Color, GodotString, VariantArray, Vector2, Vector3};
99use crate :: object:: NewRef ;
1010use crate :: private:: get_api;
1111
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+
1219/// A reference-counted CoW typed vector using Godot's pool allocator, generic over possible
1320/// element types.
1421///
@@ -19,65 +26,21 @@ use crate::private::get_api;
1926/// If you need other types, look into [`VariantArray`](struct.VariantArray.html) or directly use
2027/// `Vec<T>` for type safety.
2128///
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.
2431///
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
2739/// CoW behavior each time they are called.
2840pub struct PoolArray < T : PoolElement > {
2941 inner : T :: SysArray ,
3042}
3143
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-
8144impl < T : PoolElement > PoolArray < T > {
8245 /// Creates an empty array.
8346 #[ inline]
@@ -100,26 +63,56 @@ impl<T: PoolElement> PoolArray<T> {
10063 }
10164
10265 /// 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+ /// ```
10382 #[ inline]
10483 pub fn from_vec ( mut src : Vec < T > ) -> Self {
10584 let mut arr = Self :: new ( ) ;
10685 arr. append_vec ( & mut src) ;
10786 arr
10887 }
10988
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+
110103 /// Appends an element to the end of the array.
111104 ///
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] .
114107 #[ inline]
115108 pub fn push ( & mut self , val : T ) {
116109 self . push_ref ( & val)
117110 }
118111
119112 /// Appends an element to the end of the array by reference.
120113 ///
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] .
123116 #[ inline]
124117 pub fn push_ref ( & mut self , val : & T ) {
125118 unsafe {
@@ -225,7 +218,10 @@ impl<T: PoolElement> PoolArray<T> {
225218 self . len ( ) == 0
226219 }
227220
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).
229225 #[ inline]
230226 pub fn read ( & self ) -> Read < ' _ , T > {
231227 unsafe {
@@ -235,8 +231,11 @@ impl<T: PoolElement> PoolArray<T> {
235231 }
236232 }
237233
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
239235 /// 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).
240239 #[ inline]
241240 pub fn write ( & mut self ) -> Write < ' _ , T > {
242241 unsafe {
@@ -268,6 +267,8 @@ impl<T: PoolElement> PoolArray<T> {
268267impl < T : PoolElement + Copy > PoolArray < T > {
269268 /// Creates a new `PoolArray` by copying from `src`.
270269 ///
270+ /// Equivalent to
271+ ///
271272 /// # Panics
272273 ///
273274 /// If the length of `src` does not fit in `i32`.
@@ -294,6 +295,48 @@ impl<T: PoolElement + Copy> PoolArray<T> {
294295 }
295296}
296297
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+
297340// `FromIterator` and `Extend` implementations collect into `Vec` first, because Rust `Vec`s
298341// are better at handling unknown lengths than the Godot arrays (`push` CoWs every time!)
299342
0 commit comments