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