11use std:: iter:: { Extend , FromIterator } ;
22use std:: marker:: PhantomData ;
33
4- use gdnative_impl_proc_macros:: doc_variant_collection_safety;
5-
64use crate :: private:: get_api;
75use crate :: sys;
86
@@ -44,12 +42,14 @@ impl<Access: ThreadAccess> VariantArray<Access> {
4442 /// Sets the value of the element at the given offset.
4543 #[ inline]
4644 pub fn set < T : OwnedToVariant > ( & self , idx : i32 , val : T ) {
45+ self . check_bounds ( idx) ;
4746 unsafe { ( get_api ( ) . godot_array_set ) ( self . sys_mut ( ) , idx, val. owned_to_variant ( ) . sys ( ) ) }
4847 }
4948
5049 /// Returns a copy of the element at the given offset.
5150 #[ inline]
5251 pub fn get ( & self , idx : i32 ) -> Variant {
52+ self . check_bounds ( idx) ;
5353 unsafe { Variant ( ( get_api ( ) . godot_array_get ) ( self . sys ( ) , idx) ) }
5454 }
5555
@@ -63,6 +63,7 @@ impl<Access: ThreadAccess> VariantArray<Access> {
6363 /// `Variant` is reference-counted and thus cheaply cloned. Consider using `get` instead.
6464 #[ inline]
6565 pub unsafe fn get_ref ( & self , idx : i32 ) -> & Variant {
66+ self . check_bounds ( idx) ;
6667 Variant :: cast_ref ( ( get_api ( ) . godot_array_operator_index_const ) (
6768 self . sys ( ) ,
6869 idx,
@@ -79,6 +80,7 @@ impl<Access: ThreadAccess> VariantArray<Access> {
7980 #[ inline]
8081 #[ allow( clippy:: mut_from_ref) ]
8182 pub unsafe fn get_mut_ref ( & self , idx : i32 ) -> & mut Variant {
83+ self . check_bounds ( idx) ;
8284 Variant :: cast_mut_ref ( ( get_api ( ) . godot_array_operator_index ) ( self . sys_mut ( ) , idx) )
8385 }
8486
@@ -220,6 +222,15 @@ impl<Access: ThreadAccess> VariantArray<Access> {
220222 std:: mem:: forget ( self ) ;
221223 VariantArray :: from_sys ( sys)
222224 }
225+
226+ fn check_bounds ( & self , idx : i32 ) {
227+ assert ! (
228+ idx >= 0 && idx < self . len( ) ,
229+ "Index {} out of bounds (len {})" ,
230+ idx,
231+ self . len( )
232+ ) ;
233+ }
223234}
224235
225236/// Operations allowed on Dictionaries that can only be referenced to from the current thread.
@@ -335,78 +346,6 @@ impl VariantArray<Shared> {
335346 pub fn new_shared ( ) -> Self {
336347 VariantArray :: < Unique > :: new ( ) . into_shared ( )
337348 }
338-
339- /// Clears the array, resizing to 0.
340- ///
341- #[ doc_variant_collection_safety]
342- #[ inline]
343- pub unsafe fn clear ( & self ) {
344- ( get_api ( ) . godot_array_clear ) ( self . sys_mut ( ) ) ;
345- }
346-
347- /// Removes the element at `idx`.
348- ///
349- #[ doc_variant_collection_safety]
350- #[ inline]
351- pub unsafe fn remove ( & self , idx : i32 ) {
352- ( get_api ( ) . godot_array_remove ) ( self . sys_mut ( ) , idx)
353- }
354-
355- /// Removed the first occurrence of `val`.
356- ///
357- #[ doc_variant_collection_safety]
358- #[ inline]
359- pub unsafe fn erase < T : ToVariant > ( & self , val : T ) {
360- ( get_api ( ) . godot_array_erase ) ( self . sys_mut ( ) , val. to_variant ( ) . sys ( ) )
361- }
362-
363- /// Resizes the array, filling with `Nil` if necessary.
364- ///
365- #[ doc_variant_collection_safety]
366- #[ inline]
367- pub unsafe fn resize ( & self , size : i32 ) {
368- ( get_api ( ) . godot_array_resize ) ( self . sys_mut ( ) , size)
369- }
370-
371- /// Appends an element at the end of the array.
372- ///
373- #[ doc_variant_collection_safety]
374- #[ inline]
375- pub unsafe fn push < T : OwnedToVariant > ( & self , val : T ) {
376- ( get_api ( ) . godot_array_push_back ) ( self . sys_mut ( ) , val. owned_to_variant ( ) . sys ( ) ) ;
377- }
378-
379- /// Removes an element at the end of the array.
380- ///
381- #[ doc_variant_collection_safety]
382- #[ inline]
383- pub unsafe fn pop ( & self ) -> Variant {
384- Variant ( ( get_api ( ) . godot_array_pop_back ) ( self . sys_mut ( ) ) )
385- }
386-
387- /// Appends an element to the front of the array.
388- ///
389- #[ doc_variant_collection_safety]
390- #[ inline]
391- pub unsafe fn push_front < T : OwnedToVariant > ( & self , val : T ) {
392- ( get_api ( ) . godot_array_push_front ) ( self . sys_mut ( ) , val. owned_to_variant ( ) . sys ( ) ) ;
393- }
394-
395- /// Removes an element at the front of the array.
396- ///
397- #[ doc_variant_collection_safety]
398- #[ inline]
399- pub unsafe fn pop_front ( & self ) -> Variant {
400- Variant ( ( get_api ( ) . godot_array_pop_front ) ( self . sys_mut ( ) ) )
401- }
402-
403- /// Insert a new int at a given position in the array.
404- ///
405- #[ doc_variant_collection_safety]
406- #[ inline]
407- pub unsafe fn insert < T : OwnedToVariant > ( & self , at : i32 , val : T ) {
408- ( get_api ( ) . godot_array_insert ) ( self . sys_mut ( ) , at, val. owned_to_variant ( ) . sys ( ) )
409- }
410349}
411350
412351/// Operations allowed on Dictionaries that may only be shared on the current thread.
@@ -675,12 +614,24 @@ godot_test!(test_array {
675614
676615godot_test ! (
677616 test_array_debug {
617+ use std:: panic:: catch_unwind;
618+
678619 let arr = VariantArray :: new( ) ; // []
679620 arr. push( & Variant :: from_str( "hello world" ) ) ;
680621 arr. push( & Variant :: from_bool( true ) ) ;
681622 arr. push( & Variant :: from_i64( 42 ) ) ;
682623
683624 assert_eq!( format!( "{:?}" , arr) , "[GodotString(hello world), Bool(True), I64(42)]" ) ;
625+
626+ let set = catch_unwind( || { arr. set( 3 , 7i64 ) ; } ) ;
627+ let get = catch_unwind( || { arr. get( 3 ) ; } ) ;
628+ let get_ref = catch_unwind( || { unsafe { arr. get_ref( 3 ) } ; } ) ;
629+ let get_mut_ref = catch_unwind( || { unsafe { arr. get_mut_ref( 3 ) } ; } ) ;
630+
631+ assert!( set. is_err( ) , "set() out of bounds causes panic" ) ;
632+ assert!( get. is_err( ) , "get() out of bounds causes panic" ) ;
633+ assert!( get_ref. is_err( ) , "get_mut() out of bounds causes panic" ) ;
634+ assert!( get_mut_ref. is_err( ) , "get_mut_ref() out of bounds causes panic" ) ;
684635 }
685636) ;
686637
0 commit comments