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