From f88c890210e7475003fe833a801f71159644cc9b Mon Sep 17 00:00:00 2001 From: Janis Date: Fri, 12 May 2023 12:13:20 +0200 Subject: [PATCH] getter for fnames, partial sdk generation, canon arg names --- src/fname.rs | 48 ++++++++++++++++++++++++ src/helper_types.rs | 9 ++++- src/lib.rs | 8 +++- src/sdk/output/rust.rs | 85 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 142 insertions(+), 8 deletions(-) diff --git a/src/fname.rs b/src/fname.rs index ae357d2..f539a84 100644 --- a/src/fname.rs +++ b/src/fname.rs @@ -1,3 +1,12 @@ +use std::{ + cell::RefCell, + collections::{hash_map::Entry, HashMap}, + sync::Mutex, +}; + +use anyhow::Context; +use once_cell::sync::{Lazy, OnceCell}; + use crate::global_tables::names::GNAMES; #[repr(C)] @@ -8,6 +17,45 @@ pub struct FName { } impl FName { + pub fn new(name: &'static str) -> anyhow::Result { + static CACHE: Lazy>>> = + Lazy::new(|| Mutex::new(RefCell::new(HashMap::new()))); + + let cache = CACHE.lock().unwrap(); + + let name = match cache.borrow_mut().entry(name) { + Entry::Occupied(entry) => Self { + comparison_index: *entry.get(), + number: 0, + }, + Entry::Vacant(entry) => { + let name = GNAMES + .read() + .unwrap() + .as_names() + .unwrap() + .iter() + .position(|entry| entry.as_str() == name) + .context("could not find fname.")? as u32; + + entry.insert(name); + + Self { + comparison_index: name, + number: 0, + } + } + }; + + Ok(name) + } + + pub fn none() -> FName { + static NAME: Lazy = Lazy::new(|| FName::new("None").expect("FName \"None\".")); + + *NAME + } + pub fn get_name(&self) -> anyhow::Result { GNAMES .read() diff --git a/src/helper_types.rs b/src/helper_types.rs index 0f1f751..adc5d79 100644 --- a/src/helper_types.rs +++ b/src/helper_types.rs @@ -1,7 +1,5 @@ use std::marker::PhantomData; -use crate::{fname::FName, tarray::FString}; - #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct TEnumAsByte { @@ -10,6 +8,13 @@ pub struct TEnumAsByte { } impl TEnumAsByte { + pub fn new(value: T) -> Self { + Self { + inner: unsafe { *core::mem::transmute::<_, *const u8>(&value as *const T) }, + phantom: PhantomData, + } + } + pub fn as_enum(&self) -> &T { unsafe { &*core::mem::transmute::<_, *const T>(&self.inner as *const u8) } } diff --git a/src/lib.rs b/src/lib.rs index d11d66f..67a3816 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -423,7 +423,11 @@ pub mod sdk { let param = MethodParameter { name: format!( "Arg{}", - prop.get_name().context("failed to get parameter name")? + canonicalize_name( + &prop + .get_name() + .context("failed to get parameter name")? + ) ), ty, }; @@ -735,7 +739,7 @@ pub mod sdk { fn canonicalize_name(name: &str) -> Cow { let valid = split_at_illegal_char(name).into_valid(); - if keywords().contains(valid.as_ref()) { + if keywords().contains(valid.as_ref()) || valid.starts_with(|c: char| !c.is_alphabetic()) { Cow::Owned(format!("_{}", &valid)) } else { valid diff --git a/src/sdk/output/rust.rs b/src/sdk/output/rust.rs index 47b3ba1..4ade41d 100644 --- a/src/sdk/output/rust.rs +++ b/src/sdk/output/rust.rs @@ -1,4 +1,7 @@ -use std::io::{BufWriter, Write}; +use std::{ + collections::HashSet, + io::{BufWriter, Write}, +}; use anyhow::Context; use itertools::Itertools; @@ -8,7 +11,10 @@ use crate::{ canonicalize_name, Class, ClassField, ClassMethod, Enum, PrimitiveType, ProcessedPackage, Sdk, Type, Types, }, - v2_types::traits::{AsUObject, UObjectNonConst, UStructNonConst}, + v2_types::{ + traits::{AsUObject, UObjectNonConst, UStructNonConst}, + UObject, + }, }; pub trait RustType { @@ -201,7 +207,7 @@ impl AsPtr for {name} {{ w, r#" impl {name} {{ - fn zeroed() -> Self {{ + pub fn zeroed() -> Self {{ unsafe {{ core::mem::MaybeUninit::::zeroed().assume_init() }} }} }} @@ -464,6 +470,77 @@ impl {name} {{ Ok(()) } +pub fn generate_partial_sdk_to_tmp( + sdk: &Sdk, + packages: HashSet<&'static str>, +) -> anyhow::Result<()> { + std::fs::create_dir_all("z:/tmp/ark_sdk/")?; + let file = std::fs::File::create("z:/tmp/ark_sdk/mod.rs")?; + let mut writer = BufWriter::new(file); + + writeln!(writer, "use core::cell::UnsafeCell;")?; + writeln!(writer, "use core::ptr::NonNull;")?; + writeln!(writer, "use super::AsPtr;")?; + writeln!(writer, "use super::process_event;")?; + writeln!(writer, "use super::StaticClass;")?; + + let packages = sdk.packages.iter().filter(|(_, pkg)| { + let pkg_name = canonicalize_name( + &pkg.package + .get_full_name() + .expect("could not get package name"), + ) + .to_string(); + + packages.contains(pkg_name.as_str()) + }); + + let mut processed_packages = HashSet::new(); + + for (obj, pkg) in packages { + if processed_packages.insert(*obj) { + generate_package(sdk, &mut writer, &mut processed_packages, pkg)?; + } + } + + todo!() +} + +fn generate_package( + sdk: &Sdk, + writer: &mut W, + processed_packages: &mut HashSet, + pkg: &ProcessedPackage, +) -> anyhow::Result<()> { + let pkg_name = canonicalize_name( + &pkg.package + .get_full_name() + .context("could not get package name")?, + ) + .to_string(); + + writeln!(writer, "pub mod {pkg_name};")?; + + let file = std::fs::File::create(format!("z:/tmp/ark_sdk/{pkg_name}.rs"))?; + let mut file = BufWriter::new(file); + generate_package_rust_module(pkg, sdk, &mut file)?; + + for (obj, _) in pkg.package_dependencies.iter() { + if processed_packages.insert(*obj) { + generate_package( + sdk, + writer, + processed_packages, + sdk.packages + .get(obj) + .context("could not find dependency package")?, + )?; + } + } + + Ok(()) +} + pub fn generate_sdk_to_tmp(sdk: &Sdk) -> anyhow::Result<()> { std::fs::create_dir_all("z:/tmp/ark_sdk/")?; let file = std::fs::File::create("z:/tmp/ark_sdk/mod.rs")?; @@ -506,7 +583,7 @@ pub fn generate_package_rust_module( for (pkg, _) in &pkg.package_dependencies { writeln!( w, - "use {}::*;", + "pub use {}::*;", canonicalize_name(&pkg.get_full_name().context("could not get package name")?) )?; }