unreal-sdk/src/tarray.rs
Janis 724939e5da extracted fname and tarray from raw types into own modules
- tarray and fname are pretty independent from the rest of the type system
2023-04-20 02:36:46 +02:00

105 lines
2.3 KiB
Rust

use std::{ops::Index, ptr::NonNull, slice::SliceIndex};
#[repr(C)]
#[derive(Debug)]
pub struct TArray<T> {
data: Option<NonNull<T>>,
count: u32,
max: u32,
}
unsafe impl<T> Send for TArray<T> where T: Send {}
unsafe impl<T> Sync for TArray<T> where T: Sync {}
pub type FString = TArray<u16>;
impl ToString for FString {
fn to_string(&self) -> String {
widestring::U16CStr::from_slice(&self)
.expect("invalid utf16 string")
.to_string_lossy()
}
}
impl<T> TArray<T> {
pub fn len(&self) -> usize {
self.count as usize
}
pub fn capacity(&self) -> usize {
self.max as usize
}
pub fn as_slice(&self) -> &[T] {
match self.data {
Some(ptr) => unsafe { core::slice::from_raw_parts(ptr.as_ptr(), self.len()) },
None => unsafe { core::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0) },
}
}
pub fn as_slice_mut(&mut self) -> &mut [T] {
match self.data {
Some(ptr) => unsafe { core::slice::from_raw_parts_mut(ptr.as_ptr(), self.len()) },
None => unsafe { core::slice::from_raw_parts_mut(NonNull::dangling().as_ptr(), 0) },
}
}
}
impl<T, I: SliceIndex<[T]>> Index<I> for TArray<T> {
type Output = I::Output;
fn index(&self, i: I) -> &Self::Output {
let data = self.as_slice();
&data[i]
}
}
impl<T> std::ops::Deref for TArray<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
pub struct IntoIter<T> {
//array_ref: &'a TArray<T>,
ptr: *const T,
end: *const T,
}
impl<'a, T> IntoIter<T> {
pub fn new(array: &'a TArray<T>) -> Self {
let ptr = array.data.unwrap().as_ptr();
Self {
ptr,
end: unsafe { ptr.offset(array.count as isize) },
}
}
}
impl<'a, T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
if self.ptr == self.end {
None
} else {
let old = self.ptr;
self.ptr = unsafe { self.ptr.offset(1) };
Some(unsafe { std::ptr::read(old) })
}
}
}
impl<'a, T> IntoIterator for &'a TArray<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter::new(self)
}
}