From 396ee1e80968337606d9e202007fc499e3256f8b Mon Sep 17 00:00:00 2001 From: Janis Date: Sun, 23 Apr 2023 05:12:48 +0200 Subject: [PATCH] allocator api for TArray, fixes - check if class is AActor when checking if type is an actor type with A prefix - param types public, with public fields - sort types alphabetically when generating files --- src/lib.rs | 12 +++-- src/sdk/output/rust.rs | 10 ++-- src/tarray.rs | 111 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 124 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2c228c1..d11d66f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ const_ptr_as_ref, const_nonnull_new, let_chains, + allocator_api, if_let_guard )] @@ -175,7 +176,8 @@ pub mod sdk { let is_actor = strct .iter_super_structs() - .contains(&unsafe { actor_static_class().unwrap().cast() }); + .contains(&unsafe { actor_static_class().unwrap().cast() }) + || strct.is_a_maybe(&actor_static_class()); let is_class = strct.is_a(&UClass::static_class().unwrap()); let super_struct = if let Some(spr) = *strct.super_field() { @@ -419,10 +421,10 @@ pub mod sdk { log::debug!("field: {ty:?}: {prop}"); let param = MethodParameter { - name: prop - .get_name() - .context("failed to get parameter name")? - .to_lowercase(), + name: format!( + "Arg{}", + prop.get_name().context("failed to get parameter name")? + ), ty, }; diff --git a/src/sdk/output/rust.rs b/src/sdk/output/rust.rs index 1cc2c6a..47b3ba1 100644 --- a/src/sdk/output/rust.rs +++ b/src/sdk/output/rust.rs @@ -1,6 +1,7 @@ use std::io::{BufWriter, Write}; use anyhow::Context; +use itertools::Itertools; use crate::{ sdk::{ @@ -439,10 +440,10 @@ pub fn generate_method_params( w: &mut W, ) -> anyhow::Result<()> { let name = format!("{}_{}_Params", class.rust_name(), method.name); - write!(w, "#[repr(C)]\n#[derive(Debug)]\nstruct {name} {{\n")?; + write!(w, "#[repr(C)]\n#[derive(Debug)]\npub struct {name} {{\n")?; for param in &method.parameters { - write!(w, "\t{}: ", param.as_param().name)?; + write!(w, "\tpub {}: ", param.as_param().name)?; param.as_param().ty.rust_type(sdk, w)?; write!(w, ",\n")?; } @@ -510,7 +511,10 @@ pub fn generate_package_rust_module( )?; } - for (_, ty) in &pkg.types { + for (_, ty) in pkg.types.iter().sorted_by(|a, b| { + a.0.get_full_name_or_default() + .cmp(&b.0.get_full_name_or_default()) + }) { match ty { Types::Class(class) => { generate_class(&class, sdk, w)?; diff --git a/src/tarray.rs b/src/tarray.rs index 93128b4..c0cd0b5 100644 --- a/src/tarray.rs +++ b/src/tarray.rs @@ -1,4 +1,20 @@ -use std::{ops::Index, ptr::NonNull, slice::SliceIndex}; +use std::{ + ops::{Index, IndexMut}, + ptr::NonNull, + slice::SliceIndex, +}; + +use once_cell::sync::OnceCell; + +static ALLOCATOR: OnceCell> = + OnceCell::new(); + +pub fn set_allocator(ally: A) +where + A: std::alloc::Allocator + Send + Sync + 'static, +{ + _ = ALLOCATOR.set(Box::new(ally)); +} #[repr(C)] #[derive(Debug)] @@ -19,7 +35,86 @@ impl ToString for FString { } } +impl Drop for TArray { + fn drop(&mut self) { + if let Some(ptr) = self.data { + unsafe { + ALLOCATOR + .get() + .expect("allocator") + .deallocate(ptr.cast(), std::alloc::Layout::for_value(ptr.as_ref())); + } + } + } +} + impl TArray { + pub fn new() -> Self { + Self { + data: None, + count: 0, + max: 0, + } + } + + pub unsafe fn set_len(&mut self, size: usize) { + self.count = (size as u32).min(self.max); + } + + pub fn reserve(&mut self, size: usize) { + self.ensure_space(size); + } + + fn ensure_space(&mut self, size: usize) { + if self.data.is_none() || size >= self.max as usize { + self.grow(size.max(self.max as usize * 2)); + } + } + + fn grow(&mut self, new_size: usize) { + if new_size <= self.max as usize { + return; + } + + if self.max == 0 || self.data.is_none() { + if let Some(alloc) = ALLOCATOR.get() { + match alloc.allocate(std::alloc::Layout::array::(32).unwrap()) { + Ok(ptr) => { + self.data = Some(ptr.cast()); + self.max = ptr.len() as u32; + } + Err(e) => { + log::error!("failed to allocate with UE4 allocator: {e}."); + } + } + } + } else if let Some(alloc) = ALLOCATOR.get() { + unsafe { + match alloc.grow_zeroed( + self.data.unwrap().cast(), + std::alloc::Layout::array::(self.max as usize).unwrap(), + std::alloc::Layout::array::(new_size).unwrap(), + ) { + Ok(ptr) => { + self.data = Some(ptr.cast()); + self.max = ptr.len() as u32; + } + Err(e) => { + log::error!("failed to allocate with UE4 allocator: {e}."); + } + } + } + } + } + + pub fn push(&mut self, value: T) { + self.ensure_space(self.count as usize + 1); + self.data.map(|ptr| unsafe { + ptr.as_ptr().offset(self.count as isize).write(value); + self.count += 1; + }); + } + pub fn len(&self) -> usize { self.count as usize } @@ -53,6 +148,14 @@ impl> Index for TArray { } } +impl> IndexMut for TArray { + fn index_mut(&mut self, i: I) -> &mut Self::Output { + let data = self.as_slice_mut(); + + &mut data[i] + } +} + impl std::ops::Deref for TArray { type Target = [T]; @@ -61,6 +164,12 @@ impl std::ops::Deref for TArray { } } +impl std::ops::DerefMut for TArray { + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_slice_mut() + } +} + pub struct IntoIter { //array_ref: &'a TArray, ptr: *const T,