use crate::api;
use crate::structs::core::Class;
use std::ffi::c_void;
use std::marker::PhantomData;
#[repr(C)]
pub struct ArrayBounds {
pub length: usize,
pub lower_bound: i32,
}
#[repr(C)]
pub struct Il2cppArray<T> {
pub klass: *mut c_void,
pub monitor: *mut c_void,
pub bounds: *mut ArrayBounds,
pub max_length: usize,
phantom: PhantomData<T>,
}
impl<T: Copy> Il2cppArray<T> {
pub fn get_data(&self) -> usize {
let header_size = std::mem::size_of::<Self>();
(self as *const Self as usize) + header_size
}
pub fn get(&self, index: usize) -> T {
if index >= self.max_length {
panic!("Index out of bounds: {} >= {}", index, self.max_length);
}
unsafe {
let element_ptr = (self.get_data() + index * std::mem::size_of::<T>()) as *const T;
*element_ptr
}
}
pub fn at(&self, index: usize) -> T {
self.get(index)
}
pub fn set(&mut self, index: usize, value: T) {
if index >= self.max_length {
panic!("Index out of bounds: {} >= {}", index, self.max_length);
}
unsafe {
let element_ptr = (self.get_data() + index * std::mem::size_of::<T>()) as *mut T;
*element_ptr = value;
}
}
pub fn get_pointer(&self) -> *const T {
let header_size = std::mem::size_of::<Self>();
((self as *const Self as usize) + header_size) as *const T
}
pub fn insert(&mut self, arr: &[T], size: usize, index: usize) {
if (size + index) >= self.max_length {
if index >= self.max_length {
return;
}
let new_size = self.max_length - index;
for (i, &item) in arr.iter().enumerate().take(new_size) {
self.set(i + index, item);
}
} else {
for (i, &item) in arr.iter().enumerate().take(size) {
self.set(i + index, item);
}
}
}
pub fn fill(&mut self, value: T) {
for i in 0..self.max_length {
self.set(i, value);
}
}
pub fn remove_at(&mut self, index: usize) {
if index >= self.max_length {
return;
}
if index + 1 < self.max_length {
unsafe {
let data = self.get_pointer() as *mut T;
std::ptr::copy(
data.add(index + 1),
data.add(index),
self.max_length - index - 1,
);
}
}
}
pub fn remove_range(&mut self, index: usize, mut count: usize) {
if index >= self.max_length {
return;
}
if count == 0 {
count = 1;
}
let count = count.min(self.max_length - index);
let tail_len = self.max_length - index - count;
if tail_len > 0 {
unsafe {
let data = self.get_pointer() as *mut T;
std::ptr::copy(data.add(index + count), data.add(index), tail_len);
}
}
}
pub fn remove_all(&mut self) {}
pub fn to_vector(&self) -> Vec<T> {
let mut result = Vec::with_capacity(self.max_length);
for i in 0..self.max_length {
result.push(self.at(i));
}
result
}
pub fn new(class: &Class, size: usize) -> *mut Self {
unsafe { api::array_new(class.address, size as u32) as *mut Self }
}
}