use crate::get_api;
use crate::sys;
use crate::Variant;
pub struct VariantArray(pub(crate) sys::godot_array);
impl VariantArray {
pub fn new() -> Self {
VariantArray::default()
}
pub fn set(&mut self, idx: i32, val: &Variant) {
unsafe { (get_api().godot_array_set)(&mut self.0, idx, &val.0) }
}
pub fn get_val(&mut self, idx: i32) -> Variant {
unsafe { Variant((get_api().godot_array_get)(&self.0, idx)) }
}
pub fn get_ref(&self, idx: i32) -> &Variant {
unsafe { Variant::cast_ref((get_api().godot_array_operator_index_const)(&self.0, idx)) }
}
pub fn get_mut_ref(&mut self, idx: i32) -> &mut Variant {
unsafe { Variant::cast_mut_ref((get_api().godot_array_operator_index)(&mut self.0, idx)) }
}
pub fn count(&mut self, val: &Variant) -> i32 {
unsafe { (get_api().godot_array_count)(&mut self.0, &val.0) }
}
pub fn clear(&mut self) {
unsafe {
(get_api().godot_array_clear)(&mut self.0);
}
}
pub fn remove(&mut self, idx: i32) {
unsafe { (get_api().godot_array_remove)(&mut self.0, idx) }
}
pub fn erase(&mut self, val: &Variant) {
unsafe { (get_api().godot_array_erase)(&mut self.0, &val.0) }
}
pub fn is_empty(&self) -> bool {
unsafe { (get_api().godot_array_empty)(&self.0) }
}
pub fn len(&self) -> i32 {
unsafe { (get_api().godot_array_size)(&self.0) }
}
pub fn push(&mut self, val: &Variant) {
unsafe {
(get_api().godot_array_push_back)(&mut self.0, &val.0);
}
}
pub fn pop(&mut self) -> Variant {
unsafe { Variant((get_api().godot_array_pop_back)(&mut self.0)) }
}
pub fn push_front(&mut self, val: &Variant) {
unsafe {
(get_api().godot_array_push_front)(&mut self.0, &val.0);
}
}
pub fn pop_front(&mut self) -> Variant {
unsafe { Variant((get_api().godot_array_pop_front)(&mut self.0)) }
}
pub fn insert(&mut self, at: i32, val: &Variant) {
unsafe { (get_api().godot_array_insert)(&mut self.0, at, &val.0) }
}
pub fn find(&self, what: &Variant, from: i32) -> i32 {
unsafe { (get_api().godot_array_find)(&self.0, &what.0, from) }
}
pub fn contains(&self, what: &Variant) -> bool {
unsafe { (get_api().godot_array_has)(&self.0, &what.0) }
}
pub fn resize(&mut self, size: i32) {
unsafe { (get_api().godot_array_resize)(&mut self.0, size) }
}
pub fn rfind(&self, what: &Variant, from: i32) -> i32 {
unsafe { (get_api().godot_array_rfind)(&self.0, &what.0, from) }
}
pub fn find_last(&self, what: &Variant) -> i32 {
unsafe { (get_api().godot_array_find_last)(&self.0, &what.0) }
}
pub fn invert(&mut self) {
unsafe { (get_api().godot_array_invert)(&mut self.0) }
}
pub fn hash(&self) -> i32 {
unsafe { (get_api().godot_array_hash)(&self.0) }
}
pub fn sort(&mut self) {
unsafe { (get_api().godot_array_sort)(&mut self.0) }
}
pub fn iter(&self) -> Iter {
Iter {
arr: self,
range: 0..self.len(),
}
}
pub fn iter_mut(&mut self) -> IterMut {
let len = self.len();
IterMut {
arr: self,
range: 0..len,
}
}
#[doc(hidden)]
pub fn sys(&self) -> *const sys::godot_array {
&self.0
}
#[doc(hidden)]
pub fn from_sys(sys: sys::godot_array) -> Self {
VariantArray(sys)
}
impl_common_methods! {
pub fn new_ref(&self) -> VariantArray : godot_array_new_copy;
}
}
impl_basic_traits!(
for VariantArray as godot_array {
Drop => godot_array_destroy;
Default => godot_array_new;
}
);
pub struct Iter<'a> {
arr: &'a VariantArray,
range: std::ops::Range<i32>,
}
impl<'a> Iterator for Iter<'a> {
type Item = &'a Variant;
fn next(&mut self) -> Option<Self::Item> {
self.range.next().map(|idx| self.arr.get_ref(idx))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
}
}
pub struct IterMut<'a> {
arr: &'a mut VariantArray,
range: std::ops::Range<i32>,
}
impl<'a> Iterator for IterMut<'a> {
type Item = &'a mut Variant;
fn next(&mut self) -> Option<Self::Item> {
self.range.next().map(|idx| {
let short_ref: &'_ mut Variant = self.arr.get_mut_ref(idx);
unsafe { std::mem::transmute::<_, &'a mut Variant>(short_ref) }
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
}
}
godot_test!(test_array {
let foo = Variant::from_str("foo");
let bar = Variant::from_str("bar");
let nope = Variant::from_str("nope");
let mut array = VariantArray::new();
assert!(array.is_empty());
assert_eq!(array.len(), 0);
array.push(&foo); array.push(&bar);
assert_eq!(array.len(), 2);
assert!(array.contains(&foo));
assert!(array.contains(&bar));
assert!(!array.contains(&nope));
array.set(0, &bar); array.set(1, &foo);
assert_eq!(array.get_ref(0), &bar);
assert_eq!(array.get_ref(1), &foo);
array.pop(); array.pop();
let x = Variant::from_i64(42);
let y = Variant::from_i64(1337);
let z = Variant::from_i64(512);
array.insert(0, &x); array.insert(0, &y); array.push_front(&z); array.push_front(&z);
assert_eq!(array.find(&y, 0), 2);
assert_eq!(array.find_last(&z), 1);
assert_eq!(array.find(&nope, 0), -1);
array.invert();
assert_eq!(array.get_ref(0), &x);
array.pop_front(); array.pop_front();
assert_eq!(array.get_ref(0), &z);
array.resize(0); assert!(array.is_empty());
array.push(&foo); array.push(&bar);
let array2 = array.new_ref();
assert!(array2.contains(&foo));
assert!(array2.contains(&bar));
assert!(!array2.contains(&nope));
let mut array3 = VariantArray::new();
array3.push(&Variant::from_i64(42));
array3.push(&Variant::from_i64(1337));
array3.push(&Variant::from_i64(512));
assert_eq!(
&[42, 1337, 512],
array3.iter().map(|v| v.try_to_i64().unwrap()).collect::<Vec<_>>().as_slice(),
);
for v in array3.iter_mut() {
*v = Variant::from_i64(54);
}
assert_eq!(
&[54, 54, 54],
array3.iter().map(|v| v.try_to_i64().unwrap()).collect::<Vec<_>>().as_slice(),
);
});