Skip to main content

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