godot_core/builtin/collections/array.rs
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
8use std::marker::PhantomData;
9use std::{cmp, fmt};
10
11use crate::builtin::*;
12use crate::meta;
13use crate::meta::error::{ConvertError, FromGodotError, FromVariantError};
14use crate::meta::{
15 element_godot_type_name, element_variant_type, ArrayElement, ArrayTypeInfo, AsArg, ByRef,
16 ClassName, ExtVariantType, FromGodot, GodotConvert, GodotFfiVariant, GodotType, ParamType,
17 PropertyHintInfo, RefArg, ToGodot,
18};
19use crate::obj::{bounds, Bounds, DynGd, Gd, GodotClass};
20use crate::registry::property::{BuiltinExport, Export, Var};
21use godot_ffi as sys;
22use sys::{ffi_methods, interface_fn, GodotFfi};
23
24/// Godot's `Array` type.
25///
26/// Unlike GDScript, all indices and sizes are unsigned, so negative indices are not supported.
27///
28/// # Typed arrays
29///
30/// Godot's `Array` can be either typed or untyped.
31///
32/// An untyped array can contain any kind of [`Variant`], even different types in the same array.
33/// We represent this in Rust as `VariantArray`, which is just a type alias for `Array<Variant>`.
34///
35/// Godot also supports typed arrays, which are also just `Variant` arrays under the hood, but with
36/// runtime checks, so that no values of the wrong type are inserted into the array. We represent this as
37/// `Array<T>`, where the type `T` must implement `ArrayElement`. Some types like `Array<T>` cannot
38/// be stored inside arrays, as Godot prevents nesting.
39///
40/// If you plan to use any integer or float types apart from `i64` and `f64`, read
41/// [this documentation](../meta/trait.ArrayElement.html#integer-and-float-types).
42///
43/// # Reference semantics
44///
45/// Like in GDScript, `Array` acts as a reference type: multiple `Array` instances may
46/// refer to the same underlying array, and changes to one are visible in the other.
47///
48/// To create a copy that shares data with the original array, use [`Clone::clone()`].
49/// If you want to create a copy of the data, use [`duplicate_shallow()`][Self::duplicate_shallow]
50/// or [`duplicate_deep()`][Self::duplicate_deep].
51///
52/// # Typed array example
53///
54/// ```no_run
55/// # use godot::prelude::*;
56/// // Create typed Array<i64> and add values.
57/// let mut array = Array::new();
58/// array.push(10);
59/// array.push(20);
60/// array.push(30);
61///
62/// // Or create the same array in a single expression.
63/// let array = array![10, 20, 30];
64///
65/// // Access elements.
66/// let value: i64 = array.at(0); // 10
67/// let maybe: Option<i64> = array.get(3); // None
68///
69/// // Iterate over i64 elements.
70/// for value in array.iter_shared() {
71/// println!("{value}");
72/// }
73///
74/// // Clone array (shares the reference), and overwrite elements through clone.
75/// let mut cloned = array.clone();
76/// cloned.set(0, 50); // [50, 20, 30]
77/// cloned.remove(1); // [50, 30]
78/// cloned.pop(); // [50]
79///
80/// // Changes will be reflected in the original array.
81/// assert_eq!(array.len(), 1);
82/// assert_eq!(array.front(), Some(50));
83/// ```
84///
85/// # Untyped array example
86///
87/// ```no_run
88/// # use godot::prelude::*;
89/// // VariantArray allows dynamic element types.
90/// let mut array = VariantArray::new();
91/// array.push(&10.to_variant());
92/// array.push(&"Hello".to_variant());
93///
94/// // Or equivalent, use the `varray!` macro which converts each element.
95/// let array = varray![10, "Hello"];
96///
97/// // Access elements.
98/// let value: Variant = array.at(0);
99/// let value: i64 = array.at(0).to(); // Variant::to() extracts i64.
100/// let maybe: Result<i64, _> = array.at(1).try_to(); // "Hello" is not i64 -> Err.
101/// let maybe: Option<Variant> = array.get(3);
102///
103/// // ...and so on.
104/// ```
105///
106/// # Thread safety
107///
108/// Usage is safe if the `Array` is used on a single thread only. Concurrent reads on
109/// different threads are also safe, but any writes must be externally synchronized. The Rust
110/// compiler will enforce this as long as you use only Rust threads, but it cannot protect against
111/// concurrent modification on other threads (e.g. created through GDScript).
112///
113/// # Element type safety
114///
115/// We provide a richer set of element types than Godot, for convenience and stronger invariants in your _Rust_ code.
116/// This, however, means that the Godot representation of such arrays is not capable of incorporating the additional "Rust-side" information.
117/// This can lead to situations where GDScript code or the editor UI can insert values that do not fulfill the Rust-side invariants.
118/// The library offers some best-effort protection in Debug mode, but certain errors may only occur on element access, in the form of panics.
119///
120/// Concretely, the following types lose type information when passed to Godot. If you want 100% bullet-proof arrays, avoid those.
121/// - Non-`i64` integers: `i8`, `i16`, `i32`, `u8`, `u16`, `u32`. (`u64` is unsupported).
122/// - Non-`f64` floats: `f32`.
123/// - Non-null objects: [`Gd<T>`][crate::obj::Gd].
124/// Godot generally allows `null` in arrays due to default-constructability, e.g. when using `resize()`.
125/// The Godot-faithful (but less convenient) alternative is to use `Option<Gd<T>>` element types.
126/// - Objects with dyn-trait association: [`DynGd<T, D>`][crate::obj::DynGd].
127/// Godot doesn't know Rust traits and will only see the `T` part.
128///
129/// # Godot docs
130///
131/// [`Array[T]` (stable)](https://docs.godotengine.org/en/stable/classes/class_array.html)
132pub struct Array<T: ArrayElement> {
133 // Safety Invariant: The type of all values in `opaque` matches the type `T`.
134 opaque: sys::types::OpaqueArray,
135 _phantom: PhantomData<T>,
136}
137
138/// Guard that can only call immutable methods on the array.
139struct ImmutableInnerArray<'a> {
140 inner: inner::InnerArray<'a>,
141}
142
143impl<'a> std::ops::Deref for ImmutableInnerArray<'a> {
144 type Target = inner::InnerArray<'a>;
145
146 fn deref(&self) -> &Self::Target {
147 &self.inner
148 }
149}
150
151/// A Godot `Array` without an assigned type.
152pub type VariantArray = Array<Variant>;
153
154// TODO check if these return a typed array
155impl_builtin_froms!(VariantArray;
156 PackedByteArray => array_from_packed_byte_array,
157 PackedColorArray => array_from_packed_color_array,
158 PackedFloat32Array => array_from_packed_float32_array,
159 PackedFloat64Array => array_from_packed_float64_array,
160 PackedInt32Array => array_from_packed_int32_array,
161 PackedInt64Array => array_from_packed_int64_array,
162 PackedStringArray => array_from_packed_string_array,
163 PackedVector2Array => array_from_packed_vector2_array,
164 PackedVector3Array => array_from_packed_vector3_array,
165);
166
167#[cfg(since_api = "4.3")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.3")))]
168impl_builtin_froms!(VariantArray;
169 PackedVector4Array => array_from_packed_vector4_array,
170);
171
172impl<T: ArrayElement> Array<T> {
173 fn from_opaque(opaque: sys::types::OpaqueArray) -> Self {
174 // Note: type is not yet checked at this point, because array has not yet been initialized!
175 Self {
176 opaque,
177 _phantom: PhantomData,
178 }
179 }
180
181 /// Constructs an empty `Array`.
182 pub fn new() -> Self {
183 Self::default()
184 }
185
186 /// ⚠️ Returns the value at the specified index.
187 ///
188 /// This replaces the `Index` trait, which cannot be implemented for `Array` as references are not guaranteed to remain valid.
189 ///
190 /// # Panics
191 ///
192 /// If `index` is out of bounds. If you want to handle out-of-bounds access, use [`get()`](Self::get) instead.
193 pub fn at(&self, index: usize) -> T {
194 // Panics on out-of-bounds.
195 let ptr = self.ptr(index);
196
197 // SAFETY: `ptr` is a live pointer to a variant since `ptr.is_null()` just verified that the index is not out of bounds.
198 let variant = unsafe { Variant::borrow_var_sys(ptr) };
199 T::from_variant(variant)
200 }
201
202 /// Returns the value at the specified index, or `None` if the index is out-of-bounds.
203 ///
204 /// If you know the index is correct, use [`at()`](Self::at) instead.
205 pub fn get(&self, index: usize) -> Option<T> {
206 let ptr = self.ptr_or_null(index);
207 if ptr.is_null() {
208 None
209 } else {
210 // SAFETY: `ptr` is a live pointer to a variant since `ptr.is_null()` just verified that the index is not out of bounds.
211 let variant = unsafe { Variant::borrow_var_sys(ptr) };
212 Some(T::from_variant(variant))
213 }
214 }
215
216 /// Returns `true` if the array contains the given value. Equivalent of `has` in GDScript.
217 pub fn contains(&self, value: impl AsArg<T>) -> bool {
218 meta::arg_into_ref!(value: T);
219 self.as_inner().has(&value.to_variant())
220 }
221
222 /// Returns the number of times a value is in the array.
223 pub fn count(&self, value: impl AsArg<T>) -> usize {
224 meta::arg_into_ref!(value: T);
225 to_usize(self.as_inner().count(&value.to_variant()))
226 }
227
228 /// Returns the number of elements in the array. Equivalent of `size()` in Godot.
229 ///
230 /// Retrieving the size incurs an FFI call. If you know the size hasn't changed, you may consider storing
231 /// it in a variable. For loops, prefer iterators.
232 #[doc(alias = "size")]
233 pub fn len(&self) -> usize {
234 to_usize(self.as_inner().size())
235 }
236
237 /// Returns `true` if the array is empty.
238 ///
239 /// Checking for emptiness incurs an FFI call. If you know the size hasn't changed, you may consider storing
240 /// it in a variable. For loops, prefer iterators.
241 pub fn is_empty(&self) -> bool {
242 self.as_inner().is_empty()
243 }
244
245 /// Returns a 32-bit integer hash value representing the array and its contents.
246 ///
247 /// Note: Arrays with equal content will always produce identical hash values. However, the
248 /// reverse is not true. Returning identical hash values does not imply the arrays are equal,
249 /// because different arrays can have identical hash values due to hash collisions.
250 pub fn hash(&self) -> u32 {
251 // The GDExtension interface only deals in `i64`, but the engine's own `hash()` function
252 // actually returns `uint32_t`.
253 self.as_inner().hash().try_into().unwrap()
254 }
255
256 /// Returns the first element in the array, or `None` if the array is empty.
257 #[doc(alias = "first")]
258 pub fn front(&self) -> Option<T> {
259 (!self.is_empty()).then(|| {
260 let variant = self.as_inner().front();
261 T::from_variant(&variant)
262 })
263 }
264
265 /// Returns the last element in the array, or `None` if the array is empty.
266 #[doc(alias = "last")]
267 pub fn back(&self) -> Option<T> {
268 (!self.is_empty()).then(|| {
269 let variant = self.as_inner().back();
270 T::from_variant(&variant)
271 })
272 }
273
274 /// Clears the array, removing all elements.
275 pub fn clear(&mut self) {
276 self.debug_ensure_mutable();
277
278 // SAFETY: No new values are written to the array, we only remove values from the array.
279 unsafe { self.as_inner_mut() }.clear();
280 }
281
282 /// Sets the value at the specified index.
283 ///
284 /// # Panics
285 ///
286 /// If `index` is out of bounds.
287 pub fn set(&mut self, index: usize, value: impl AsArg<T>) {
288 self.debug_ensure_mutable();
289
290 let ptr_mut = self.ptr_mut(index);
291
292 meta::arg_into_ref!(value: T);
293 let variant = value.to_variant();
294
295 // SAFETY: `ptr_mut` just checked that the index is not out of bounds.
296 unsafe { variant.move_into_var_ptr(ptr_mut) };
297 }
298
299 /// Appends an element to the end of the array.
300 ///
301 /// _Godot equivalents: `append` and `push_back`_
302 #[doc(alias = "append")]
303 #[doc(alias = "push_back")]
304 pub fn push(&mut self, value: impl AsArg<T>) {
305 self.debug_ensure_mutable();
306
307 meta::arg_into_ref!(value: T);
308
309 // SAFETY: The array has type `T` and we're writing a value of type `T` to it.
310 let mut inner = unsafe { self.as_inner_mut() };
311 inner.push_back(&value.to_variant());
312 }
313
314 /// Adds an element at the beginning of the array, in O(n).
315 ///
316 /// On large arrays, this method is much slower than [`push()`][Self::push], as it will move all the array's elements.
317 /// The larger the array, the slower `push_front()` will be.
318 pub fn push_front(&mut self, value: impl AsArg<T>) {
319 self.debug_ensure_mutable();
320
321 meta::arg_into_ref!(value: T);
322
323 // SAFETY: The array has type `T` and we're writing a value of type `T` to it.
324 let mut inner_array = unsafe { self.as_inner_mut() };
325 inner_array.push_front(&value.to_variant());
326 }
327
328 /// Removes and returns the last element of the array. Returns `None` if the array is empty.
329 ///
330 /// _Godot equivalent: `pop_back`_
331 #[doc(alias = "pop_back")]
332 pub fn pop(&mut self) -> Option<T> {
333 self.debug_ensure_mutable();
334
335 (!self.is_empty()).then(|| {
336 // SAFETY: We do not write any values to the array, we just remove one.
337 let variant = unsafe { self.as_inner_mut() }.pop_back();
338 T::from_variant(&variant)
339 })
340 }
341
342 /// Removes and returns the first element of the array, in O(n). Returns `None` if the array is empty.
343 ///
344 /// Note: On large arrays, this method is much slower than `pop()` as it will move all the
345 /// array's elements. The larger the array, the slower `pop_front()` will be.
346 pub fn pop_front(&mut self) -> Option<T> {
347 self.debug_ensure_mutable();
348
349 (!self.is_empty()).then(|| {
350 // SAFETY: We do not write any values to the array, we just remove one.
351 let variant = unsafe { self.as_inner_mut() }.pop_front();
352 T::from_variant(&variant)
353 })
354 }
355
356 /// ⚠️ Inserts a new element before the index. The index must be valid or the end of the array (`index == len()`).
357 ///
358 /// On large arrays, this method is much slower than [`push()`][Self::push], as it will move all the array's elements after the inserted element.
359 /// The larger the array, the slower `insert()` will be.
360 ///
361 /// # Panics
362 /// If `index > len()`.
363 pub fn insert(&mut self, index: usize, value: impl AsArg<T>) {
364 self.debug_ensure_mutable();
365
366 let len = self.len();
367 assert!(
368 index <= len,
369 "Array insertion index {index} is out of bounds: length is {len}",
370 );
371
372 meta::arg_into_ref!(value: T);
373
374 // SAFETY: The array has type `T` and we're writing a value of type `T` to it.
375 unsafe { self.as_inner_mut() }.insert(to_i64(index), &value.to_variant());
376 }
377
378 /// ⚠️ Removes and returns the element at the specified index. Equivalent of `pop_at` in GDScript.
379 ///
380 /// On large arrays, this method is much slower than [`pop()`][Self::pop] as it will move all the array's
381 /// elements after the removed element. The larger the array, the slower `remove()` will be.
382 ///
383 /// # Panics
384 ///
385 /// If `index` is out of bounds.
386 #[doc(alias = "pop_at")]
387 pub fn remove(&mut self, index: usize) -> T {
388 self.debug_ensure_mutable();
389
390 self.check_bounds(index);
391
392 // SAFETY: We do not write any values to the array, we just remove one.
393 let variant = unsafe { self.as_inner_mut() }.pop_at(to_i64(index));
394 T::from_variant(&variant)
395 }
396
397 /// Removes the first occurrence of a value from the array.
398 ///
399 /// If the value does not exist in the array, nothing happens. To remove an element by index, use [`remove()`][Self::remove] instead.
400 ///
401 /// On large arrays, this method is much slower than [`pop()`][Self::pop], as it will move all the array's
402 /// elements after the removed element.
403 pub fn erase(&mut self, value: impl AsArg<T>) {
404 self.debug_ensure_mutable();
405
406 meta::arg_into_ref!(value: T);
407
408 // SAFETY: We don't write anything to the array.
409 unsafe { self.as_inner_mut() }.erase(&value.to_variant());
410 }
411
412 /// Assigns the given value to all elements in the array. This can be used together with
413 /// `resize` to create an array with a given size and initialized elements.
414 pub fn fill(&mut self, value: impl AsArg<T>) {
415 self.debug_ensure_mutable();
416
417 meta::arg_into_ref!(value: T);
418
419 // SAFETY: The array has type `T` and we're writing values of type `T` to it.
420 unsafe { self.as_inner_mut() }.fill(&value.to_variant());
421 }
422
423 /// Resizes the array to contain a different number of elements.
424 ///
425 /// If the new size is smaller than the current size, then it removes elements from the end. If the new size is bigger than the current one
426 /// then the new elements are set to `value`.
427 ///
428 /// If you know that the new size is smaller, then consider using [`shrink`](Array::shrink) instead.
429 pub fn resize(&mut self, new_size: usize, value: impl AsArg<T>) {
430 self.debug_ensure_mutable();
431
432 let original_size = self.len();
433
434 // SAFETY: While we do insert `Variant::nil()` if the new size is larger, we then fill it with `value` ensuring that all values in the
435 // array are of type `T` still.
436 unsafe { self.as_inner_mut() }.resize(to_i64(new_size));
437
438 meta::arg_into_ref!(value: T);
439
440 // If new_size < original_size then this is an empty iterator and does nothing.
441 for i in original_size..new_size {
442 // Exception safety: if to_variant() panics, the array will become inconsistent (filled with non-T nils).
443 // At the moment (Nov 2024), this can only happen for u64, which isn't a valid Array element type.
444 // This could be changed to use clone() (if that doesn't panic) or store a variant without moving.
445 let variant = value.to_variant();
446
447 let ptr_mut = self.ptr_mut(i);
448
449 // SAFETY: we iterate pointer within bounds; ptr_mut() additionally checks them.
450 // ptr_mut() lookup could be optimized if we know the internal layout.
451 unsafe { variant.move_into_var_ptr(ptr_mut) };
452 }
453 }
454
455 /// Shrinks the array down to `new_size`.
456 ///
457 /// This will only change the size of the array if `new_size` is smaller than the current size. Returns `true` if the array was shrunk.
458 ///
459 /// If you want to increase the size of the array, use [`resize`](Array::resize) instead.
460 #[doc(alias = "resize")]
461 pub fn shrink(&mut self, new_size: usize) -> bool {
462 self.debug_ensure_mutable();
463
464 if new_size >= self.len() {
465 return false;
466 }
467
468 // SAFETY: Since `new_size` is less than the current size, we'll only be removing elements from the array.
469 unsafe { self.as_inner_mut() }.resize(to_i64(new_size));
470
471 true
472 }
473
474 /// Appends another array at the end of this array. Equivalent of `append_array` in GDScript.
475 pub fn extend_array(&mut self, other: &Array<T>) {
476 self.debug_ensure_mutable();
477
478 // SAFETY: `append_array` will only read values from `other`, and all types can be converted to `Variant`.
479 let other: &VariantArray = unsafe { other.assume_type_ref::<Variant>() };
480
481 // SAFETY: `append_array` will only write values gotten from `other` into `self`, and all values in `other` are guaranteed
482 // to be of type `T`.
483 let mut inner_self = unsafe { self.as_inner_mut() };
484 inner_self.append_array(other);
485 }
486
487 /// Returns a shallow copy of the array. All array elements are copied, but any reference types
488 /// (such as `Array`, `Dictionary` and `Object`) will still refer to the same value.
489 ///
490 /// To create a deep copy, use [`duplicate_deep()`][Self::duplicate_deep] instead.
491 /// To create a new reference to the same array data, use [`clone()`][Clone::clone].
492 pub fn duplicate_shallow(&self) -> Self {
493 // SAFETY: We never write to the duplicated array, and all values read are read as `Variant`.
494 let duplicate: VariantArray = unsafe { self.as_inner().duplicate(false) };
495
496 // SAFETY: duplicate() returns a typed array with the same type as Self, and all values are taken from `self` so have the right type.
497 unsafe { duplicate.assume_type() }
498 }
499
500 /// Returns a deep copy of the array. All nested arrays and dictionaries are duplicated and
501 /// will not be shared with the original array. Note that any `Object`-derived elements will
502 /// still be shallow copied.
503 ///
504 /// To create a shallow copy, use [`duplicate_shallow()`][Self::duplicate_shallow] instead.
505 /// To create a new reference to the same array data, use [`clone()`][Clone::clone].
506 pub fn duplicate_deep(&self) -> Self {
507 // SAFETY: We never write to the duplicated array, and all values read are read as `Variant`.
508 let duplicate: VariantArray = unsafe { self.as_inner().duplicate(true) };
509
510 // SAFETY: duplicate() returns a typed array with the same type as Self, and all values are taken from `self` so have the right type.
511 unsafe { duplicate.assume_type() }
512 }
513
514 /// Returns a sub-range `begin..end`, as a new array.
515 ///
516 /// The values of `begin` (inclusive) and `end` (exclusive) will be clamped to the array size.
517 ///
518 /// If specified, `step` is the relative index between source elements. It can be negative,
519 /// in which case `begin` must be higher than `end`. For example,
520 /// `Array::from(&[0, 1, 2, 3, 4, 5]).slice(5, 1, -2)` returns `[5, 3]`.
521 ///
522 /// Array elements are copied to the slice, but any reference types (such as `Array`,
523 /// `Dictionary` and `Object`) will still refer to the same value. To create a deep copy, use
524 /// [`subarray_deep()`][Self::subarray_deep] instead.
525 ///
526 /// _Godot equivalent: `slice`_
527 #[doc(alias = "slice")]
528 // TODO(v0.3): change to i32 like NodePath::slice/subpath() and support+test negative indices.
529 pub fn subarray_shallow(&self, begin: usize, end: usize, step: Option<isize>) -> Self {
530 self.subarray_impl(begin, end, step, false)
531 }
532
533 /// Returns a sub-range `begin..end`, as a new `Array`.
534 ///
535 /// The values of `begin` (inclusive) and `end` (exclusive) will be clamped to the array size.
536 ///
537 /// If specified, `step` is the relative index between source elements. It can be negative,
538 /// in which case `begin` must be higher than `end`. For example,
539 /// `Array::from(&[0, 1, 2, 3, 4, 5]).slice(5, 1, -2)` returns `[5, 3]`.
540 ///
541 /// All nested arrays and dictionaries are duplicated and will not be shared with the original
542 /// array. Note that any `Object`-derived elements will still be shallow copied. To create a
543 /// shallow copy, use [`subarray_shallow()`][Self::subarray_shallow] instead.
544 ///
545 /// _Godot equivalent: `slice`_
546 #[doc(alias = "slice")]
547 // TODO(v0.3): change to i32 like NodePath::slice/subpath() and support+test negative indices.
548 pub fn subarray_deep(&self, begin: usize, end: usize, step: Option<isize>) -> Self {
549 self.subarray_impl(begin, end, step, true)
550 }
551
552 fn subarray_impl(&self, begin: usize, end: usize, step: Option<isize>, deep: bool) -> Self {
553 assert_ne!(step, Some(0), "subarray: step cannot be zero");
554
555 let len = self.len();
556 let begin = begin.min(len);
557 let end = end.min(len);
558 let step = step.unwrap_or(1);
559
560 // SAFETY: The type of the array is `T` and we convert the returned array to an `Array<T>` immediately.
561 let subarray: VariantArray = unsafe {
562 self.as_inner()
563 .slice(to_i64(begin), to_i64(end), step.try_into().unwrap(), deep)
564 };
565
566 // SAFETY: slice() returns a typed array with the same type as Self
567 unsafe { subarray.assume_type() }
568 }
569
570 /// Returns an iterator over the elements of the `Array`. Note that this takes the array
571 /// by reference but returns its elements by value, since they are internally converted from
572 /// `Variant`.
573 ///
574 /// Notice that it's possible to modify the `Array` through another reference while
575 /// iterating over it. This will not result in unsoundness or crashes, but will cause the
576 /// iterator to behave in an unspecified way.
577 pub fn iter_shared(&self) -> Iter<'_, T> {
578 Iter {
579 array: self,
580 next_idx: 0,
581 }
582 }
583
584 /// Returns the minimum value contained in the array if all elements are of comparable types.
585 ///
586 /// If the elements can't be compared or the array is empty, `None` is returned.
587 pub fn min(&self) -> Option<T> {
588 let min = self.as_inner().min();
589 (!min.is_nil()).then(|| T::from_variant(&min))
590 }
591
592 /// Returns the maximum value contained in the array if all elements are of comparable types.
593 ///
594 /// If the elements can't be compared or the array is empty, `None` is returned.
595 pub fn max(&self) -> Option<T> {
596 let max = self.as_inner().max();
597 (!max.is_nil()).then(|| T::from_variant(&max))
598 }
599
600 /// Returns a random element from the array, or `None` if it is empty.
601 pub fn pick_random(&self) -> Option<T> {
602 (!self.is_empty()).then(|| {
603 let variant = self.as_inner().pick_random();
604 T::from_variant(&variant)
605 })
606 }
607
608 /// Searches the array for the first occurrence of a value and returns its index, or `None` if
609 /// not found.
610 ///
611 /// Starts searching at index `from`; pass `None` to search the entire array.
612 pub fn find(&self, value: impl AsArg<T>, from: Option<usize>) -> Option<usize> {
613 meta::arg_into_ref!(value: T);
614
615 let from = to_i64(from.unwrap_or(0));
616 let index = self.as_inner().find(&value.to_variant(), from);
617 if index >= 0 {
618 Some(index.try_into().unwrap())
619 } else {
620 None
621 }
622 }
623
624 /// Searches the array backwards for the last occurrence of a value and returns its index, or
625 /// `None` if not found.
626 ///
627 /// Starts searching at index `from`; pass `None` to search the entire array.
628 pub fn rfind(&self, value: impl AsArg<T>, from: Option<usize>) -> Option<usize> {
629 meta::arg_into_ref!(value: T);
630
631 let from = from.map(to_i64).unwrap_or(-1);
632 let index = self.as_inner().rfind(&value.to_variant(), from);
633
634 // It's not documented, but `rfind` returns -1 if not found.
635 if index >= 0 {
636 Some(to_usize(index))
637 } else {
638 None
639 }
640 }
641
642 /// Finds the index of a value in a sorted array using binary search.
643 ///
644 /// If the value is not present in the array, returns the insertion index that would maintain sorting order.
645 ///
646 /// Calling `bsearch` on an unsorted array results in unspecified behavior. Consider using `sort()` to ensure the sorting
647 /// order is compatible with your callable's ordering.
648 pub fn bsearch(&self, value: impl AsArg<T>) -> usize {
649 meta::arg_into_ref!(value: T);
650
651 to_usize(self.as_inner().bsearch(&value.to_variant(), true))
652 }
653
654 /// Finds the index of a value in a sorted array using binary search, with type-safe custom predicate.
655 ///
656 /// The comparator function should return an ordering that indicates whether its argument is `Less`, `Equal` or `Greater` the desired value.
657 /// For example, for an ascending-ordered array, a simple predicate searching for a constant value would be `|elem| elem.cmp(&4)`.
658 /// See also [`slice::binary_search_by()`].
659 ///
660 /// If the value is found, returns `Ok(index)` with its index. Otherwise, returns `Err(index)`, where `index` is the insertion index
661 /// that would maintain sorting order.
662 ///
663 /// Calling `bsearch_by` on an unsorted array results in unspecified behavior. Consider using [`sort_by()`] to ensure
664 /// the sorting order is compatible with your callable's ordering.
665 #[cfg(since_api = "4.2")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.2")))]
666 pub fn bsearch_by<F>(&self, mut func: F) -> Result<usize, usize>
667 where
668 F: FnMut(&T) -> cmp::Ordering + 'static,
669 {
670 // Early exit; later code relies on index 0 being present.
671 if self.is_empty() {
672 return Err(0);
673 }
674
675 // We need one dummy element of type T, because Godot's bsearch_custom() checks types (so Variant::nil() can't be passed).
676 // Optimization: roundtrip Variant -> T -> Variant could be avoided, but anyone needing speed would use Rust binary search...
677 let ignored_value = self.at(0);
678 let ignored_value = meta::val_into_arg(ignored_value); //AsArg::into_arg(&ignored_value);
679
680 let godot_comparator = |args: &[&Variant]| {
681 let value = T::from_variant(args[0]);
682 let is_less = matches!(func(&value), cmp::Ordering::Less);
683
684 Ok(is_less.to_variant())
685 };
686
687 let debug_name = std::any::type_name::<F>();
688 let index = Callable::with_scoped_fn(debug_name, godot_comparator, |pred| {
689 self.bsearch_custom(ignored_value, pred)
690 });
691
692 if let Some(value_at_index) = self.get(index) {
693 if func(&value_at_index) == cmp::Ordering::Equal {
694 return Ok(index);
695 }
696 }
697
698 Err(index)
699 }
700
701 /// Finds the index of a value in a sorted array using binary search, with `Callable` custom predicate.
702 ///
703 /// The callable `pred` takes two elements `(a, b)` and should return if `a < b` (strictly less).
704 /// For a type-safe version, check out [`bsearch_by()`][Self::bsearch_by].
705 ///
706 /// If the value is not present in the array, returns the insertion index that would maintain sorting order.
707 ///
708 /// Calling `bsearch_custom` on an unsorted array results in unspecified behavior. Consider using `sort_custom()` to ensure
709 /// the sorting order is compatible with your callable's ordering.
710 pub fn bsearch_custom(&self, value: impl AsArg<T>, pred: &Callable) -> usize {
711 meta::arg_into_ref!(value: T);
712
713 to_usize(
714 self.as_inner()
715 .bsearch_custom(&value.to_variant(), pred, true),
716 )
717 }
718
719 /// Reverses the order of the elements in the array.
720 pub fn reverse(&mut self) {
721 self.debug_ensure_mutable();
722
723 // SAFETY: We do not write any values that don't already exist in the array, so all values have the correct type.
724 unsafe { self.as_inner_mut() }.reverse();
725 }
726
727 /// Sorts the array.
728 ///
729 /// The sorting algorithm used is not [stable](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability).
730 /// This means that values considered equal may have their order changed when using `sort_unstable`. For most variant types,
731 /// this distinction should not matter though.
732 ///
733 /// _Godot equivalent: `Array.sort()`_
734 #[doc(alias = "sort")]
735 pub fn sort_unstable(&mut self) {
736 self.debug_ensure_mutable();
737
738 // SAFETY: We do not write any values that don't already exist in the array, so all values have the correct type.
739 unsafe { self.as_inner_mut() }.sort();
740 }
741
742 /// Sorts the array, using a type-safe comparator.
743 ///
744 /// The predicate expects two parameters `(a, b)` and should return an ordering relation. For example, simple ascending ordering of the
745 /// elements themselves would be achieved with `|a, b| a.cmp(b)`.
746 ///
747 /// The sorting algorithm used is not [stable](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability).
748 /// This means that values considered equal may have their order changed when using `sort_unstable_by`. For most variant types,
749 /// this distinction should not matter though.
750 #[cfg(since_api = "4.2")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.2")))]
751 pub fn sort_unstable_by<F>(&mut self, mut func: F)
752 where
753 F: FnMut(&T, &T) -> cmp::Ordering,
754 {
755 self.debug_ensure_mutable();
756
757 let godot_comparator = |args: &[&Variant]| {
758 let lhs = T::from_variant(args[0]);
759 let rhs = T::from_variant(args[1]);
760 let is_less = matches!(func(&lhs, &rhs), cmp::Ordering::Less);
761
762 Ok(is_less.to_variant())
763 };
764
765 let debug_name = std::any::type_name::<F>();
766 Callable::with_scoped_fn(debug_name, godot_comparator, |pred| {
767 self.sort_unstable_custom(pred)
768 });
769 }
770
771 /// Sorts the array, using type-unsafe `Callable` comparator.
772 ///
773 /// For a type-safe variant of this method, use [`sort_unstable_by()`][Self::sort_unstable_by].
774 ///
775 /// The callable expects two parameters `(lhs, rhs)` and should return a bool `lhs < rhs`.
776 ///
777 /// The sorting algorithm used is not [stable](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability).
778 /// This means that values considered equal may have their order changed when using `sort_unstable_custom`.For most variant types,
779 /// this distinction should not matter though.
780 ///
781 /// _Godot equivalent: `Array.sort_custom()`_
782 #[doc(alias = "sort_custom")]
783 pub fn sort_unstable_custom(&mut self, func: &Callable) {
784 self.debug_ensure_mutable();
785
786 // SAFETY: We do not write any values that don't already exist in the array, so all values have the correct type.
787 unsafe { self.as_inner_mut() }.sort_custom(func);
788 }
789
790 /// Shuffles the array such that the items will have a random order. This method uses the
791 /// global random number generator common to methods such as `randi`. Call `randomize` to
792 /// ensure that a new seed will be used each time if you want non-reproducible shuffling.
793 pub fn shuffle(&mut self) {
794 self.debug_ensure_mutable();
795
796 // SAFETY: We do not write any values that don't already exist in the array, so all values have the correct type.
797 unsafe { self.as_inner_mut() }.shuffle();
798 }
799
800 /// Turns the array into a shallow-immutable array.
801 ///
802 /// Makes the array read-only and returns the original array. The array's elements cannot be overridden with different values, and their
803 /// order cannot change. Does not apply to nested elements, such as dictionaries. This operation is irreversible.
804 ///
805 /// In GDScript, arrays are automatically read-only if declared with the `const` keyword.
806 ///
807 /// # Semantics and alternatives
808 /// You can use this in Rust, but the behavior of mutating methods is only validated in a best-effort manner (more than in GDScript though):
809 /// some methods like `set()` panic in Debug mode, when used on a read-only array. There is no guarantee that any attempts to change result
810 /// in feedback; some may silently do nothing.
811 ///
812 /// In Rust, you can use shared references (`&Array<T>`) to prevent mutation. Note however that `Clone` can be used to create another
813 /// reference, through which mutation can still occur. For deep-immutable arrays, you'll need to keep your `Array` encapsulated or directly
814 /// use Rust data structures.
815 ///
816 /// _Godot equivalent: `make_read_only`_
817 #[doc(alias = "make_read_only")]
818 pub fn into_read_only(self) -> Self {
819 // SAFETY: Changes a per-array property, no elements.
820 unsafe { self.as_inner_mut() }.make_read_only();
821 self
822 }
823
824 /// Returns true if the array is read-only.
825 ///
826 /// See [`into_read_only()`][Self::into_read_only].
827 /// In GDScript, arrays are automatically read-only if declared with the `const` keyword.
828 pub fn is_read_only(&self) -> bool {
829 self.as_inner().is_read_only()
830 }
831
832 /// Best-effort mutability check.
833 ///
834 /// # Panics
835 /// In Debug mode, if the array is marked as read-only.
836 fn debug_ensure_mutable(&self) {
837 debug_assert!(
838 !self.is_read_only(),
839 "mutating operation on read-only array"
840 );
841 }
842
843 /// Asserts that the given index refers to an existing element.
844 ///
845 /// # Panics
846 /// If `index` is out of bounds.
847 fn check_bounds(&self, index: usize) {
848 let len = self.len();
849 assert!(
850 index < len,
851 "Array index {index} is out of bounds: length is {len}",
852 );
853 }
854
855 /// Returns a pointer to the element at the given index.
856 ///
857 /// # Panics
858 /// If `index` is out of bounds.
859 fn ptr(&self, index: usize) -> sys::GDExtensionConstVariantPtr {
860 let ptr = self.ptr_or_null(index);
861 assert!(
862 !ptr.is_null(),
863 "Array index {index} out of bounds (len {len})",
864 len = self.len(),
865 );
866 ptr
867 }
868
869 /// Returns a pointer to the element at the given index, or null if out of bounds.
870 fn ptr_or_null(&self, index: usize) -> sys::GDExtensionConstVariantPtr {
871 // SAFETY: array_operator_index_const returns null for invalid indexes.
872 let variant_ptr = unsafe {
873 let index = to_i64(index);
874 interface_fn!(array_operator_index_const)(self.sys(), index)
875 };
876
877 // Signature is wrong in GDExtension, semantically this is a const ptr
878 sys::SysPtr::as_const(variant_ptr)
879 }
880
881 /// Returns a mutable pointer to the element at the given index.
882 ///
883 /// # Panics
884 ///
885 /// If `index` is out of bounds.
886 fn ptr_mut(&mut self, index: usize) -> sys::GDExtensionVariantPtr {
887 let ptr = self.ptr_mut_or_null(index);
888 assert!(
889 !ptr.is_null(),
890 "Array index {index} out of bounds (len {len})",
891 len = self.len(),
892 );
893 ptr
894 }
895
896 /// Returns a pointer to the element at the given index, or null if out of bounds.
897 fn ptr_mut_or_null(&mut self, index: usize) -> sys::GDExtensionVariantPtr {
898 // SAFETY: array_operator_index returns null for invalid indexes.
899 unsafe {
900 let index = to_i64(index);
901 interface_fn!(array_operator_index)(self.sys_mut(), index)
902 }
903 }
904
905 /// # Safety
906 ///
907 /// This has the same safety issues as doing `self.assume_type::<Variant>()` and so the relevant safety invariants from
908 /// [`assume_type`](Self::assume_type) must be upheld.
909 ///
910 /// In particular this means that all reads are fine, since all values can be converted to `Variant`. However, writes are only OK
911 /// if they match the type `T`.
912 #[doc(hidden)]
913 pub unsafe fn as_inner_mut(&self) -> inner::InnerArray<'_> {
914 // The memory layout of `Array<T>` does not depend on `T`.
915 inner::InnerArray::from_outer_typed(self)
916 }
917
918 fn as_inner(&self) -> ImmutableInnerArray<'_> {
919 ImmutableInnerArray {
920 // SAFETY: We can only read from the array.
921 inner: unsafe { self.as_inner_mut() },
922 }
923 }
924
925 /// Changes the generic type on this array, without changing its contents. Needed for API
926 /// functions that return a variant array even though we know its type, and for API functions
927 /// that take a variant array even though we want to pass a typed one.
928 ///
929 /// # Safety
930 ///
931 /// - Any values written to the array must match the runtime type of the array.
932 /// - Any values read from the array must be convertible to the type `U`.
933 ///
934 /// If the safety invariant of `Array` is intact, which it must be for any publicly accessible arrays, then `U` must match
935 /// the runtime type of the array. This then implies that both of the conditions above hold. This means that you only need
936 /// to keep the above conditions in mind if you are intentionally violating the safety invariant of `Array`.
937 ///
938 /// Note also that any `GodotType` can be written to a `Variant` array.
939 ///
940 /// In the current implementation, both cases will produce a panic rather than undefined behavior, but this should not be relied upon.
941 unsafe fn assume_type<U: ArrayElement>(self) -> Array<U> {
942 // The memory layout of `Array<T>` does not depend on `T`.
943 std::mem::transmute::<Array<T>, Array<U>>(self)
944 }
945
946 /// # Safety
947 /// See [`assume_type`](Self::assume_type).
948 unsafe fn assume_type_ref<U: ArrayElement>(&self) -> &Array<U> {
949 // The memory layout of `Array<T>` does not depend on `T`.
950 std::mem::transmute::<&Array<T>, &Array<U>>(self)
951 }
952
953 #[cfg(debug_assertions)] #[cfg_attr(published_docs, doc(cfg(debug_assertions)))]
954 pub(crate) fn debug_validate_elements(&self) -> Result<(), ConvertError> {
955 // SAFETY: every element is internally represented as Variant.
956 let canonical_array = unsafe { self.assume_type_ref::<Variant>() };
957
958 // If any element is not convertible, this will return an error.
959 for elem in canonical_array.iter_shared() {
960 elem.try_to::<T>().map_err(|_err| {
961 FromGodotError::BadArrayTypeInt {
962 expected: self.type_info(),
963 value: elem
964 .try_to::<i64>()
965 .expect("origin must be i64 compatible; this is a bug"),
966 }
967 .into_error(self.clone())
968 })?;
969 }
970
971 Ok(())
972 }
973
974 // No-op in Release. Avoids O(n) conversion checks, but still panics on access.
975 #[cfg(not(debug_assertions))] #[cfg_attr(published_docs, doc(cfg(not(debug_assertions))))]
976 pub(crate) fn debug_validate_elements(&self) -> Result<(), ConvertError> {
977 Ok(())
978 }
979
980 /// Returns the runtime type info of this array.
981 fn type_info(&self) -> ArrayTypeInfo {
982 let variant_type = VariantType::from_sys(
983 self.as_inner().get_typed_builtin() as sys::GDExtensionVariantType
984 );
985
986 let class_name = if variant_type == VariantType::OBJECT {
987 Some(self.as_inner().get_typed_class_name())
988 } else {
989 None
990 };
991
992 ArrayTypeInfo {
993 variant_type,
994 class_name,
995 }
996 }
997
998 /// Checks that the inner array has the correct type set on it for storing elements of type `T`.
999 fn with_checked_type(self) -> Result<Self, ConvertError> {
1000 let self_ty = self.type_info();
1001 let target_ty = ArrayTypeInfo::of::<T>();
1002
1003 if self_ty == target_ty {
1004 Ok(self)
1005 } else {
1006 Err(FromGodotError::BadArrayType {
1007 expected: target_ty,
1008 actual: self_ty,
1009 }
1010 .into_error(self))
1011 }
1012 }
1013
1014 /// Sets the type of the inner array.
1015 ///
1016 /// # Safety
1017 ///
1018 /// Must only be called once, directly after creation.
1019 unsafe fn init_inner_type(&mut self) {
1020 debug_assert!(self.is_empty());
1021 debug_assert!(!self.type_info().is_typed());
1022
1023 let type_info = ArrayTypeInfo::of::<T>();
1024 if type_info.is_typed() {
1025 let script = Variant::nil();
1026
1027 // A bit contrived because empty StringName is lazy-initialized but must also remain valid.
1028 #[allow(unused_assignments)]
1029 let mut empty_string_name = None;
1030 let class_name = if let Some(class_name) = &type_info.class_name {
1031 class_name.string_sys()
1032 } else {
1033 empty_string_name = Some(StringName::default());
1034 // as_ref() crucial here -- otherwise the StringName is dropped.
1035 empty_string_name.as_ref().unwrap().string_sys()
1036 };
1037
1038 // SAFETY: The array is a newly created empty untyped array.
1039 unsafe {
1040 interface_fn!(array_set_typed)(
1041 self.sys_mut(),
1042 type_info.variant_type.sys(),
1043 class_name, // must be empty if variant_type != OBJECT.
1044 script.var_sys(),
1045 );
1046 }
1047 }
1048 }
1049
1050 /// Returns a clone of the array without checking the resulting type.
1051 ///
1052 /// # Safety
1053 /// Should be used only in scenarios where the caller can guarantee that the resulting array will have the correct type,
1054 /// or when an incorrect Rust type is acceptable (passing raw arrays to Godot FFI).
1055 unsafe fn clone_unchecked(&self) -> Self {
1056 Self::new_with_uninit(|self_ptr| {
1057 let ctor = sys::builtin_fn!(array_construct_copy);
1058 let args = [self.sys()];
1059 ctor(self_ptr, args.as_ptr());
1060 })
1061 }
1062
1063 /// Whether this array is untyped and holds `Variant` elements (compile-time check).
1064 ///
1065 /// Used as `if` statement in trait impls. Avoids defining yet another trait or non-local overridden function just for this case;
1066 /// `Variant` is the only Godot type that has variant type NIL and can be used as an array element.
1067 fn has_variant_t() -> bool {
1068 element_variant_type::<T>() == VariantType::NIL
1069 }
1070}
1071
1072#[test]
1073fn correct_variant_t() {
1074 assert!(Array::<Variant>::has_variant_t());
1075 assert!(!Array::<i64>::has_variant_t());
1076}
1077
1078impl VariantArray {
1079 /// # Safety
1080 /// - Variant must have type `VariantType::ARRAY`.
1081 /// - Subsequent operations on this array must not rely on the type of the array.
1082 pub(crate) unsafe fn from_variant_unchecked(variant: &Variant) -> Self {
1083 // See also ffi_from_variant().
1084 Self::new_with_uninit(|self_ptr| {
1085 let array_from_variant = sys::builtin_fn!(array_from_variant);
1086 array_from_variant(self_ptr, sys::SysPtr::force_mut(variant.var_sys()));
1087 })
1088 }
1089}
1090
1091// ----------------------------------------------------------------------------------------------------------------------------------------------
1092// Traits
1093
1094// Godot has some inconsistent behavior around NaN values. In GDScript, `NAN == NAN` is `false`,
1095// but `[NAN] == [NAN]` is `true`. If they decide to make all NaNs equal, we can implement `Eq` and
1096// `Ord`; if they decide to make all NaNs unequal, we can remove this comment.
1097//
1098// impl<T> Eq for Array<T> {}
1099//
1100// impl<T> Ord for Array<T> {
1101// ...
1102// }
1103
1104// SAFETY:
1105// - `move_return_ptr`
1106// Nothing special needs to be done beyond a `std::mem::swap` when returning an Array.
1107// So we can just use `ffi_methods`.
1108//
1109// - `from_arg_ptr`
1110// Arrays are properly initialized through a `from_sys` call, but the ref-count should be incremented
1111// as that is the callee's responsibility. Which we do by calling `std::mem::forget(array.clone())`.
1112unsafe impl<T: ArrayElement> GodotFfi for Array<T> {
1113 const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(VariantType::ARRAY);
1114
1115 ffi_methods! { type sys::GDExtensionTypePtr = *mut Opaque; .. }
1116}
1117
1118// Only implement for untyped arrays; typed arrays cannot be nested in Godot.
1119impl ArrayElement for VariantArray {}
1120
1121impl<T: ArrayElement> ParamType for Array<T> {
1122 type ArgPassing = ByRef;
1123}
1124
1125impl<T: ArrayElement> GodotConvert for Array<T> {
1126 type Via = Self;
1127}
1128
1129impl<T: ArrayElement> ToGodot for Array<T> {
1130 type ToVia<'v> = Self::Via;
1131
1132 fn to_godot(&self) -> Self::ToVia<'_> {
1133 // SAFETY: only safe when passing to FFI in a context where Rust-side type doesn't matter.
1134 // TODO: avoid unsafety with either of the following:
1135 // * OutArray -- https://github.com/godot-rust/gdext/pull/806.
1136 // * Instead of cloning, use ArgRef<Array<T>>.
1137 unsafe { self.clone_unchecked() }
1138 //self.clone()
1139 }
1140
1141 fn to_variant(&self) -> Variant {
1142 self.ffi_to_variant()
1143 }
1144}
1145
1146impl<T: ArrayElement> FromGodot for Array<T> {
1147 fn try_from_godot(via: Self::Via) -> Result<Self, ConvertError> {
1148 T::debug_validate_elements(&via)?;
1149 Ok(via)
1150 }
1151}
1152
1153impl<T: ArrayElement> fmt::Debug for Array<T> {
1154 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1155 // Going through `Variant` because there doesn't seem to be a direct way.
1156 // Reuse Display.
1157 write!(f, "{}", self.to_variant().stringify())
1158 }
1159}
1160
1161impl<T: ArrayElement + fmt::Display> fmt::Display for Array<T> {
1162 /// Formats `Array` to match Godot's string representation.
1163 ///
1164 /// # Example
1165 /// ```no_run
1166 /// # use godot::prelude::*;
1167 /// let a = array![1,2,3,4];
1168 /// assert_eq!(format!("{a}"), "[1, 2, 3, 4]");
1169 /// ```
1170 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1171 write!(f, "[")?;
1172 for (count, v) in self.iter_shared().enumerate() {
1173 if count != 0 {
1174 write!(f, ", ")?;
1175 }
1176 write!(f, "{v}")?;
1177 }
1178 write!(f, "]")
1179 }
1180}
1181
1182/// Creates a new reference to the data in this array. Changes to the original array will be
1183/// reflected in the copy and vice versa.
1184///
1185/// To create a (mostly) independent copy instead, see [`Array::duplicate_shallow()`] and
1186/// [`Array::duplicate_deep()`].
1187impl<T: ArrayElement> Clone for Array<T> {
1188 fn clone(&self) -> Self {
1189 // SAFETY: `self` is a valid array, since we have a reference that keeps it alive.
1190 // Type-check follows below.
1191 let copy = unsafe { self.clone_unchecked() };
1192
1193 // Double-check copy's runtime type in Debug mode.
1194 if cfg!(debug_assertions) {
1195 copy.with_checked_type()
1196 .expect("copied array should have same type as original array")
1197 } else {
1198 copy
1199 }
1200 }
1201}
1202
1203impl<T: ArrayElement> Var for Array<T> {
1204 fn get_property(&self) -> Self::Via {
1205 self.to_godot()
1206 }
1207
1208 fn set_property(&mut self, value: Self::Via) {
1209 *self = FromGodot::from_godot(value)
1210 }
1211
1212 fn var_hint() -> PropertyHintInfo {
1213 // For array #[var], the hint string is "PackedInt32Array", "Node" etc. for typed arrays, and "" for untyped arrays.
1214 if Self::has_variant_t() {
1215 PropertyHintInfo::none()
1216 } else if sys::GdextBuild::since_api("4.2") {
1217 PropertyHintInfo::var_array_element::<T>()
1218 } else {
1219 // Godot 4.1 was not using PropertyHint::ARRAY_TYPE, but the empty hint instead.
1220 PropertyHintInfo::none()
1221 }
1222 }
1223}
1224
1225impl<T> Export for Array<T>
1226where
1227 T: ArrayElement + Export,
1228{
1229 fn export_hint() -> PropertyHintInfo {
1230 // If T == Variant, then we return "Array" builtin type hint.
1231 if Self::has_variant_t() {
1232 PropertyHintInfo::type_name::<VariantArray>()
1233 } else {
1234 PropertyHintInfo::export_array_element::<T>()
1235 }
1236 }
1237}
1238
1239impl<T: ArrayElement> BuiltinExport for Array<T> {}
1240
1241impl<T> Export for Array<Gd<T>>
1242where
1243 T: GodotClass + Bounds<Exportable = bounds::Yes>,
1244{
1245 fn export_hint() -> PropertyHintInfo {
1246 PropertyHintInfo::export_array_element::<Gd<T>>()
1247 }
1248
1249 #[doc(hidden)]
1250 fn as_node_class() -> Option<ClassName> {
1251 PropertyHintInfo::object_as_node_class::<T>()
1252 }
1253}
1254
1255/// `#[export]` for `Array<DynGd<T, D>>` is available only for `T` being Engine class (such as Node or Resource).
1256///
1257/// Consider exporting `Array<Gd<T>>` instead of `Array<DynGd<T, D>>` for user-declared GDExtension classes.
1258impl<T: GodotClass, D> Export for Array<DynGd<T, D>>
1259where
1260 T: GodotClass + Bounds<Exportable = bounds::Yes>,
1261 D: ?Sized + 'static,
1262{
1263 fn export_hint() -> PropertyHintInfo {
1264 PropertyHintInfo::export_array_element::<DynGd<T, D>>()
1265 }
1266
1267 #[doc(hidden)]
1268 fn as_node_class() -> Option<ClassName> {
1269 PropertyHintInfo::object_as_node_class::<T>()
1270 }
1271}
1272
1273impl<T: ArrayElement> Default for Array<T> {
1274 #[inline]
1275 fn default() -> Self {
1276 let mut array = unsafe {
1277 Self::new_with_uninit(|self_ptr| {
1278 let ctor = sys::builtin_fn!(array_construct_default);
1279 ctor(self_ptr, std::ptr::null_mut())
1280 })
1281 };
1282
1283 // SAFETY: We just created this array, and haven't called `init_inner_type` before.
1284 unsafe { array.init_inner_type() };
1285 array
1286 }
1287}
1288
1289// T must be GodotType (or subtrait ArrayElement), because drop() requires sys_mut(), which is on the GodotFfi trait.
1290// Its sister method GodotFfi::from_sys_init() requires Default, which is only implemented for T: GodotType.
1291// This could be addressed by splitting up GodotFfi if desired.
1292impl<T: ArrayElement> Drop for Array<T> {
1293 #[inline]
1294 fn drop(&mut self) {
1295 unsafe {
1296 let array_destroy = sys::builtin_fn!(array_destroy);
1297 array_destroy(self.sys_mut());
1298 }
1299 }
1300}
1301
1302impl<T: ArrayElement> GodotType for Array<T> {
1303 type Ffi = Self;
1304
1305 type ToFfi<'f>
1306 = RefArg<'f, Array<T>>
1307 where
1308 Self: 'f;
1309
1310 fn to_ffi(&self) -> Self::ToFfi<'_> {
1311 RefArg::new(self)
1312 }
1313
1314 fn into_ffi(self) -> Self::Ffi {
1315 self
1316 }
1317
1318 fn try_from_ffi(ffi: Self::Ffi) -> Result<Self, ConvertError> {
1319 Ok(ffi)
1320 }
1321
1322 fn godot_type_name() -> String {
1323 "Array".to_string()
1324 }
1325
1326 #[cfg(since_api = "4.2")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.2")))]
1327 fn property_hint_info() -> PropertyHintInfo {
1328 // Array<Variant>, aka untyped array, has no hints.
1329 if Self::has_variant_t() {
1330 return PropertyHintInfo::none();
1331 }
1332
1333 // Typed arrays use type hint.
1334 PropertyHintInfo {
1335 hint: crate::global::PropertyHint::ARRAY_TYPE,
1336 hint_string: GString::from(element_godot_type_name::<T>()),
1337 }
1338 }
1339}
1340
1341impl<T: ArrayElement> GodotFfiVariant for Array<T> {
1342 fn ffi_to_variant(&self) -> Variant {
1343 unsafe {
1344 Variant::new_with_var_uninit(|variant_ptr| {
1345 let array_to_variant = sys::builtin_fn!(array_to_variant);
1346 array_to_variant(variant_ptr, sys::SysPtr::force_mut(self.sys()));
1347 })
1348 }
1349 }
1350
1351 fn ffi_from_variant(variant: &Variant) -> Result<Self, ConvertError> {
1352 // First check if the variant is an array. The array conversion shouldn't be called otherwise.
1353 if variant.get_type() != Self::VARIANT_TYPE.variant_as_nil() {
1354 return Err(FromVariantError::BadType {
1355 expected: Self::VARIANT_TYPE.variant_as_nil(),
1356 actual: variant.get_type(),
1357 }
1358 .into_error(variant.clone()));
1359 }
1360
1361 let array = unsafe {
1362 Self::new_with_uninit(|self_ptr| {
1363 let array_from_variant = sys::builtin_fn!(array_from_variant);
1364 array_from_variant(self_ptr, sys::SysPtr::force_mut(variant.var_sys()));
1365 })
1366 };
1367
1368 // Then, check the runtime type of the array.
1369 array.with_checked_type()
1370 }
1371}
1372
1373// ----------------------------------------------------------------------------------------------------------------------------------------------
1374// Conversion traits
1375
1376/// Creates a `Array` from the given Rust array.
1377impl<T: ArrayElement + ToGodot, const N: usize> From<&[T; N]> for Array<T> {
1378 fn from(arr: &[T; N]) -> Self {
1379 Self::from(&arr[..])
1380 }
1381}
1382
1383/// Creates a `Array` from the given slice.
1384impl<T: ArrayElement + ToGodot> From<&[T]> for Array<T> {
1385 fn from(slice: &[T]) -> Self {
1386 let mut array = Self::new();
1387 let len = slice.len();
1388 if len == 0 {
1389 return array;
1390 }
1391
1392 // SAFETY: We fill the array with `Variant::nil()`, however since we're resizing to the size of the slice we'll end up rewriting all
1393 // the nulls with values of type `T`.
1394 unsafe { array.as_inner_mut() }.resize(to_i64(len));
1395
1396 // SAFETY: `array` has `len` elements since we just resized it, and they are all valid `Variant`s. Additionally, since
1397 // the array was created in this function, and we do not access the array while this slice exists, the slice has unique
1398 // access to the elements.
1399 let elements = unsafe { Variant::borrow_slice_mut(array.ptr_mut(0), len) };
1400 for (element, array_slot) in slice.iter().zip(elements.iter_mut()) {
1401 *array_slot = element.to_variant();
1402 }
1403
1404 array
1405 }
1406}
1407
1408/// Creates a `Array` from an iterator.
1409impl<T: ArrayElement + ToGodot> FromIterator<T> for Array<T> {
1410 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1411 let mut array = Self::new();
1412 array.extend(iter);
1413 array
1414 }
1415}
1416
1417/// Extends a `Array` with the contents of an iterator.
1418impl<T: ArrayElement> Extend<T> for Array<T> {
1419 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1420 // Unfortunately the GDExtension API does not offer the equivalent of `Vec::reserve`.
1421 // Otherwise, we could use it to pre-allocate based on `iter.size_hint()`.
1422 //
1423 // A faster implementation using `resize()` and direct pointer writes might still be possible.
1424 // Note that this could technically also use iter(), since no moves need to happen (however Extend requires IntoIterator).
1425 for item in iter.into_iter() {
1426 // self.push(AsArg::into_arg(&item));
1427 self.push(meta::val_into_arg(item));
1428 }
1429 }
1430}
1431
1432/// Converts this array to a strongly typed Rust vector.
1433impl<T: ArrayElement + FromGodot> From<&Array<T>> for Vec<T> {
1434 fn from(array: &Array<T>) -> Vec<T> {
1435 let len = array.len();
1436 let mut vec = Vec::with_capacity(len);
1437
1438 // SAFETY: Unless `experimental-threads` is enabled, then we cannot have concurrent access to this array.
1439 // And since we don't concurrently access the array in this function, we can create a slice to its contents.
1440 let elements = unsafe { Variant::borrow_slice(array.ptr(0), len) };
1441
1442 vec.extend(elements.iter().map(T::from_variant));
1443
1444 vec
1445 }
1446}
1447
1448// ----------------------------------------------------------------------------------------------------------------------------------------------
1449
1450/// An iterator over typed elements of an [`Array`].
1451pub struct Iter<'a, T: ArrayElement> {
1452 array: &'a Array<T>,
1453 next_idx: usize,
1454}
1455
1456impl<T: ArrayElement + FromGodot> Iterator for Iter<'_, T> {
1457 type Item = T;
1458
1459 fn next(&mut self) -> Option<Self::Item> {
1460 if self.next_idx < self.array.len() {
1461 let idx = self.next_idx;
1462 self.next_idx += 1;
1463
1464 let element_ptr = self.array.ptr_or_null(idx);
1465
1466 // SAFETY: We just checked that the index is not out of bounds, so the pointer won't be null.
1467 // We immediately convert this to the right element, so barring `experimental-threads` the pointer won't be invalidated in time.
1468 let variant = unsafe { Variant::borrow_var_sys(element_ptr) };
1469 let element = T::from_variant(variant);
1470 Some(element)
1471 } else {
1472 None
1473 }
1474 }
1475
1476 fn size_hint(&self) -> (usize, Option<usize>) {
1477 let remaining = self.array.len() - self.next_idx;
1478 (remaining, Some(remaining))
1479 }
1480}
1481
1482// TODO There's a macro for this, but it doesn't support generics yet; add support and use it
1483impl<T: ArrayElement> PartialEq for Array<T> {
1484 #[inline]
1485 fn eq(&self, other: &Self) -> bool {
1486 unsafe {
1487 let mut result = false;
1488 sys::builtin_call! {
1489 array_operator_equal(self.sys(), other.sys(), result.sys_mut())
1490 }
1491 result
1492 }
1493 }
1494}
1495
1496impl<T: ArrayElement> PartialOrd for Array<T> {
1497 #[inline]
1498 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1499 let op_less = |lhs, rhs| unsafe {
1500 let mut result = false;
1501 sys::builtin_call! {
1502 array_operator_less(lhs, rhs, result.sys_mut())
1503 }
1504 result
1505 };
1506
1507 if op_less(self.sys(), other.sys()) {
1508 Some(std::cmp::Ordering::Less)
1509 } else if op_less(other.sys(), self.sys()) {
1510 Some(std::cmp::Ordering::Greater)
1511 } else if self.eq(other) {
1512 Some(std::cmp::Ordering::Equal)
1513 } else {
1514 None
1515 }
1516 }
1517}
1518
1519// ----------------------------------------------------------------------------------------------------------------------------------------------
1520
1521/// Constructs [`Array`] literals, similar to Rust's standard `vec!` macro.
1522///
1523/// The type of the array is inferred from the arguments.
1524///
1525/// # Example
1526/// ```no_run
1527/// # use godot::prelude::*;
1528/// let arr = array![3, 1, 4]; // Array<i32>
1529/// ```
1530///
1531/// # See also
1532/// To create an `Array` of variants, see the [`varray!`] macro.
1533///
1534/// For dictionaries, a similar macro [`vdict!`] exists.
1535#[macro_export]
1536macro_rules! array {
1537 ($($elements:expr),* $(,)?) => {
1538 {
1539 let mut array = $crate::builtin::Array::default();
1540 $(
1541 array.push($elements);
1542 )*
1543 array
1544 }
1545 };
1546}
1547
1548/// Constructs [`VariantArray`] literals, similar to Rust's standard `vec!` macro.
1549///
1550/// The type of the array elements is always [`Variant`].
1551///
1552/// # Example
1553/// ```no_run
1554/// # use godot::prelude::*;
1555/// let arr: VariantArray = varray![42_i64, "hello", true];
1556/// ```
1557///
1558/// # See also
1559/// To create a typed `Array` with a single element type, see the [`array!`] macro.
1560///
1561/// For dictionaries, a similar macro [`vdict!`] exists.
1562///
1563/// To construct slices of variants, use [`vslice!`].
1564#[macro_export]
1565macro_rules! varray {
1566 // Note: use to_variant() and not Variant::from(), as that works with both references and values
1567 ($($elements:expr),* $(,)?) => {
1568 {
1569 use $crate::meta::ToGodot as _;
1570 let mut array = $crate::builtin::VariantArray::default();
1571 $(
1572 array.push(&$elements.to_variant());
1573 )*
1574 array
1575 }
1576 };
1577}
1578
1579/// Constructs a slice of [`Variant`] literals, useful for passing to vararg functions.
1580///
1581/// Many APIs in Godot have variable-length arguments. GDScript can call such functions by simply passing more arguments, but in Rust,
1582/// the parameter type `&[Variant]` is used.
1583///
1584/// This macro creates a [slice](https://doc.rust-lang.org/std/primitive.slice.html) of `Variant` values.
1585///
1586/// # Examples
1587/// Variable number of arguments:
1588/// ```no_run
1589/// # use godot::prelude::*;
1590/// let slice: &[Variant] = vslice![42, "hello", true];
1591///
1592/// let concat: GString = godot::global::str(slice);
1593/// ```
1594/// _(In practice, you might want to use [`godot_str!`][crate::global::godot_str] instead of `str()`.)_
1595///
1596/// Dynamic function call via reflection. NIL can still be passed inside `vslice!`, just use `Variant::nil()`.
1597/// ```no_run
1598/// # use godot::prelude::*;
1599/// # fn some_object() -> Gd<Object> { unimplemented!() }
1600/// let mut obj: Gd<Object> = some_object();
1601/// obj.call("some_method", vslice![Vector2i::new(1, 2), Variant::nil()]);
1602/// ```
1603///
1604/// # See also
1605/// To create typed and untyped `Array`s, use the [`array!`] and [`varray!`] macros respectively.
1606///
1607/// For dictionaries, a similar macro [`vdict!`] exists.
1608#[macro_export]
1609macro_rules! vslice {
1610 // Note: use to_variant() and not Variant::from(), as that works with both references and values
1611 ($($elements:expr),* $(,)?) => {
1612 {
1613 use $crate::meta::ToGodot as _;
1614 let mut array = $crate::builtin::VariantArray::default();
1615 &[
1616 $( $elements.to_variant(), )*
1617 ]
1618 }
1619 };
1620}
1621
1622// ----------------------------------------------------------------------------------------------------------------------------------------------
1623
1624#[cfg(feature = "serde")] #[cfg_attr(published_docs, doc(cfg(feature = "serde")))]
1625mod serialize {
1626 use super::*;
1627 use serde::de::{SeqAccess, Visitor};
1628 use serde::ser::SerializeSeq;
1629 use serde::{Deserialize, Deserializer, Serialize, Serializer};
1630 use std::marker::PhantomData;
1631
1632 impl<T> Serialize for Array<T>
1633 where
1634 T: ArrayElement + Serialize,
1635 {
1636 #[inline]
1637 fn serialize<S>(
1638 &self,
1639 serializer: S,
1640 ) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
1641 where
1642 S: Serializer,
1643 {
1644 let mut sequence = serializer.serialize_seq(Some(self.len()))?;
1645 for e in self.iter_shared() {
1646 sequence.serialize_element(&e)?
1647 }
1648 sequence.end()
1649 }
1650 }
1651
1652 impl<'de, T> Deserialize<'de> for Array<T>
1653 where
1654 T: ArrayElement + Deserialize<'de>,
1655 {
1656 #[inline]
1657 fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
1658 where
1659 D: Deserializer<'de>,
1660 {
1661 struct ArrayVisitor<T>(PhantomData<T>);
1662 impl<'de, T> Visitor<'de> for ArrayVisitor<T>
1663 where
1664 T: ArrayElement + Deserialize<'de>,
1665 {
1666 type Value = Array<T>;
1667
1668 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1669 formatter.write_str(std::any::type_name::<Self::Value>())
1670 }
1671
1672 fn visit_seq<A>(
1673 self,
1674 mut seq: A,
1675 ) -> Result<Self::Value, <A as SeqAccess<'de>>::Error>
1676 where
1677 A: SeqAccess<'de>,
1678 {
1679 let mut vec = seq.size_hint().map_or_else(Vec::new, Vec::with_capacity);
1680 while let Some(val) = seq.next_element::<T>()? {
1681 vec.push(val);
1682 }
1683 Ok(Self::Value::from(vec.as_slice()))
1684 }
1685 }
1686
1687 deserializer.deserialize_seq(ArrayVisitor::<T>(PhantomData))
1688 }
1689 }
1690}