7
7
8
8
use std:: cell:: OnceCell ;
9
9
use std:: marker:: PhantomData ;
10
- use std:: ops:: RangeBounds ;
11
10
use std:: { cmp, fmt} ;
12
11
13
12
use godot_ffi as sys;
@@ -16,7 +15,7 @@ use sys::{ffi_methods, interface_fn, GodotFfi};
16
15
use crate :: builtin:: * ;
17
16
use crate :: meta;
18
17
use crate :: meta:: error:: { ConvertError , FromGodotError , FromVariantError } ;
19
- use crate :: meta:: godot_range :: GodotRange ;
18
+ use crate :: meta:: signed_range :: SignedRange ;
20
19
use crate :: meta:: {
21
20
element_godot_type_name, element_variant_type, ArrayElement , AsArg , ClassName , ElementType ,
22
21
ExtVariantType , FromGodot , GodotConvert , GodotFfiVariant , GodotType , PropertyHintInfo , RefArg ,
@@ -110,6 +109,35 @@ use crate::registry::property::{BuiltinExport, Export, Var};
110
109
/// // ...and so on.
111
110
/// ```
112
111
///
112
+ /// # Working with signed ranges and steps
113
+ ///
114
+ /// For negative indices, use [`wrapped()`](crate::meta::wrapped).
115
+ ///
116
+ /// ```no_run
117
+ /// # use godot::builtin::array;
118
+ /// # use godot::meta::wrapped;
119
+ /// let arr = array![0, 1, 2, 3, 4, 5];
120
+ ///
121
+ /// // The values of `begin` (inclusive) and `end` (exclusive) will be clamped to the array size.
122
+ /// let clamped_array = arr.subarray_deep(999..99999, None);
123
+ /// assert_eq!(clamped_array, array![]);
124
+ ///
125
+ /// // If either `begin` or `end` is negative, its value is relative to the end of the array.
126
+ /// let sub = arr.subarray_shallow(wrapped(-1..-5), None);
127
+ /// assert_eq!(sub, array![5, 3]);
128
+ ///
129
+ /// // If `end` is not specified, the range spans through whole array.
130
+ /// let sub = arr.subarray_deep(1.., None);
131
+ /// assert_eq!(sub, array![1, 2, 3, 4, 5]);
132
+ /// let other_clamped_array = arr.subarray_shallow(5.., Some(2));
133
+ /// assert_eq!(other_clamped_array, array![5]);
134
+ ///
135
+ /// // If specified, `step` is the relative index between source elements. It can be negative,
136
+ /// // in which case `begin` must be higher than `end`.
137
+ /// let sub = arr.subarray_shallow(wrapped(-1..-5), Some(-2));
138
+ /// assert_eq!(sub, array![5, 3]);
139
+ /// ```
140
+ ///
113
141
/// # Thread safety
114
142
///
115
143
/// Usage is safe if the `Array` is used on a single thread only. Concurrent reads on
@@ -530,91 +558,34 @@ impl<T: ArrayElement> Array<T> {
530
558
531
559
/// Returns a sub-range `begin..end` as a new `Array`.
532
560
///
533
- /// The values of `begin` (inclusive) and `end` (exclusive) will be clamped to the array size.
534
- ///
535
- /// If either `begin` or `end` are negative, their value is relative to the end of the array.
536
- ///
537
- /// # Example
538
- /// ```no_run
539
- /// # use godot::builtin::array;
540
- /// assert_eq!(array![0, 1, 2, 3, 4, 5].subarray_shallow(-1..-5, None), array![5, 3]);
541
- /// ```
542
- ///
543
- /// If `end` is not specified, the range spans through whole array.
544
- ///
545
- /// # Example
546
- /// ```no_run
547
- /// # use godot::builtin::array;
548
- /// assert_eq!(array![0, 1, 2, 3, 4, 5].subarray_shallow(1.., None), array![1, 2, 3, 4, 5]);
549
- /// ```
550
- ///
551
- /// If specified, `step` is the relative index between source elements. It can be negative,
552
- /// in which case `begin` must be higher than `end`.
553
- ///
554
- /// # Example
555
- /// ```no_run
556
- /// # use godot::builtin::array;
557
- /// assert_eq!(array![0, 1, 2, 3, 4, 5].subarray_shallow(-1..-5, Some(-2)), array![5, 3]);
558
- /// ```
559
- ///
560
561
/// Array elements are copied to the slice, but any reference types (such as `Array`,
561
562
/// `Dictionary` and `Object`) will still refer to the same value. To create a deep copy, use
562
563
/// [`subarray_deep()`][Self::subarray_deep] instead.
563
564
///
564
565
/// _Godot equivalent: `slice`_
565
566
#[ doc( alias = "slice" ) ]
566
- pub fn subarray_shallow ( & self , range : impl RangeBounds < i32 > , step : Option < i32 > ) -> Self {
567
+ pub fn subarray_shallow ( & self , range : impl SignedRange , step : Option < i32 > ) -> Self {
567
568
self . subarray_impl ( range, step, false )
568
569
}
569
570
570
571
/// Returns a sub-range `begin..end` as a new `Array`.
571
572
///
572
- /// The values of `begin` (inclusive) and `end` (exclusive) will be clamped to the array size.
573
- ///
574
- /// If either `begin` or `end` are negative, their value is relative to the end of the array.
575
- ///
576
- /// # Example
577
- /// ```no_run
578
- /// # use godot::builtin::array;
579
- /// assert_eq!(array![0, 1, 2, 3, 4, 5].subarray_deep(-1..-5, None), array![5, 3]);
580
- /// ```
581
- ///
582
- /// If `end` is not specified, the range spans through whole array.
583
- ///
584
- /// # Example
585
- /// ```no_run
586
- /// # use godot::builtin::array;
587
- /// assert_eq!(array![0, 1, 2, 3, 4, 5].subarray_deep(1.., None), array![1, 2, 3, 4, 5]);
588
- /// ```
589
- ///
590
- /// If specified, `step` is the relative index between source elements. It can be negative,
591
- /// in which case `begin` must be higher than `end`.
592
- ///
593
- /// # Example
594
- /// ```no_run
595
- /// # use godot::builtin::array;
596
- /// assert_eq!(array![0, 1, 2, 3, 4, 5].subarray_deep(-1..-5, Some(-2)), array![5, 3]);
597
- /// ```
598
- ///
599
573
/// All nested arrays and dictionaries are duplicated and will not be shared with the original
600
574
/// array. Note that any `Object`-derived elements will still be shallow copied. To create a
601
575
/// shallow copy, use [`subarray_shallow()`][Self::subarray_shallow] instead.
602
576
///
603
577
/// _Godot equivalent: `slice`_
604
578
#[ doc( alias = "slice" ) ]
605
- pub fn subarray_deep ( & self , range : impl RangeBounds < i32 > , step : Option < i32 > ) -> Self {
579
+ pub fn subarray_deep ( & self , range : impl SignedRange , step : Option < i32 > ) -> Self {
606
580
self . subarray_impl ( range, step, true )
607
581
}
608
582
609
583
// Note: Godot will clamp values by itself.
610
- fn subarray_impl ( & self , range : impl GodotRange < i32 > , step : Option < i32 > , deep : bool ) -> Self {
584
+ fn subarray_impl ( & self , range : impl SignedRange , step : Option < i32 > , deep : bool ) -> Self {
611
585
assert_ne ! ( step, Some ( 0 ) , "subarray: step cannot be zero" ) ;
612
586
613
587
let step = step. unwrap_or ( 1 ) ;
614
- let ( begin, end) = range. to_godot_range_fromto ( ) ;
615
-
616
- // Unbounded upper bounds are represented by `i32::MAX` instead of `i64::MAX`,
617
- // since Godot treats some indexes as 32-bit despite being declared `i64` in GDExtension API.
588
+ let ( begin, end) = range. signed ( ) ;
618
589
let end = end. unwrap_or ( i32:: MAX as i64 ) ;
619
590
620
591
// SAFETY: The type of the array is `T` and we convert the returned array to an `Array<T>` immediately.
0 commit comments