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