serialization of UStructs/UClasses/AActors

This commit is contained in:
Janis 2023-06-19 16:12:49 +02:00
parent e74ed77703
commit 47dbb8e3d1

View file

@ -1,3 +1,4 @@
use std::collections::BTreeSet;
use std::collections::{btree_map::Entry, BTreeMap};
use anyhow::Context;
@ -11,8 +12,9 @@ use crate::v2_types::{
AsUObject, UArrayPropertyTrait, UBoolPropertyTrait, UEnumPropertyTrait, UEnumTrait,
UObjectNonConst, UObjectTrait, UPropertyTrait, UStructPropertyTrait, *,
},
UClass, UEnum, UFunction, UProperty, UScriptStruct,
UClass, UEnum, UFunction, UProperty,
};
use crate::v2_types::{UScriptStruct, UStruct};
use super::repr::{
Class, ClassField, ClassMethod, Enum, Package, ProcessedPackage, Type, UnrealType,
@ -61,6 +63,7 @@ impl Enum {
});
Ok(UnrealType::Enum(Enum {
obj_ref: value.as_uobject().object_ref(),
name: value.get_name().context("could not get name")?,
full_name: value.get_full_name().context("could not get full name")?,
values,
@ -69,11 +72,107 @@ impl Enum {
}
impl Class {
pub fn from_uclass(value: UClass) -> anyhow::Result<UnrealType> {
todo!()
pub fn from_uclass(class: UClass) -> anyhow::Result<UnrealType> {
Ok(UnrealType::Class(Self {
kind: StructKind::Object,
..Self::from_struct_inner(unsafe { class.cast() })?
}))
}
pub fn from_uscriptstruct(value: UScriptStruct) -> anyhow::Result<UnrealType> {
todo!()
pub fn from_actor(class: UClass) -> anyhow::Result<UnrealType> {
Ok(UnrealType::Actor(Self {
kind: StructKind::Actor,
..Self::from_struct_inner(unsafe { class.cast() })?
}))
}
pub fn from_struct(strct: UScriptStruct) -> anyhow::Result<UnrealType> {
Ok(UnrealType::Struct(Self {
kind: StructKind::Struct,
..Self::from_struct_inner(unsafe { strct.cast() })?
}))
}
fn from_struct_inner(strct: UStruct) -> anyhow::Result<Self> {
let name = strct.get_name().context("could not get function name")?;
let full_name = strct
.get_full_name()
.context("could not get full function name")?;
let super_class = strct.super_field().and_then(|supr| {
if supr != strct {
Some(supr.as_uobject().object_ref())
} else {
None
}
});
let (fields, methods) = Self::process_children(&strct)?;
Ok(Self {
obj_ref: strct.as_uobject().object_ref(),
kind: StructKind::Struct,
size: *strct.property_size() as u32,
name,
full_name,
super_class,
properties_size: *strct.property_size() as u32,
min_alignment: *strct.min_alignment() as u32,
fields,
methods,
})
}
/// returns tuple of (fields, methods)
fn process_children(strct: &UStruct) -> anyhow::Result<(Vec<ClassField>, Vec<ClassMethod>)> {
enum ClassChild {
Field(ClassField),
Method(ClassMethod),
}
let (fields, methods) = strct
.iter_children()
.map(|field| -> anyhow::Result<Option<ClassChild>> {
let child = match any_type::AnyField::from_field(field) {
AnyField::Property(prop) => Some(ClassChild::Field(ClassField::from_uprop(prop)?)),
AnyField::Struct(strct)
if let AnyStruct::Function(func) = AnyStruct::from_struct(strct) => {
{
Some(ClassChild::Method(ClassMethod::from_ufunction(func)?))
}
}
_ => None,
};
Ok(child)
})
.fold_ok(
(Vec::new(), Vec::new()),
|(mut fields, mut methods), child| {
if let Some(child) = child {
match child {
ClassChild::Field(field) => fields.push(field),
ClassChild::Method(method) => methods.push(method),
}
}
(fields, methods)
},
)?;
Ok((fields, methods))
}
pub fn get_dependent_types(&self) -> Vec<ObjectRef> {
self.fields
.iter()
.filter_map(|field| field.ty.dependent_type())
.chain(
self.methods
.iter()
.flat_map(|method| method.get_dependent_types()),
)
.chain(self.super_class)
.collect::<Vec<_>>()
}
}
@ -90,6 +189,10 @@ impl ClassField {
ty: resolve_type(prop).context("failed to get field type")?,
})
}
pub fn get_dependent_types(&self) -> Vec<ObjectRef> {
self.ty.dependent_type().into_iter().collect()
}
}
impl ClassMethod {
@ -115,6 +218,13 @@ impl ClassMethod {
parameters: params,
})
}
pub fn get_dependent_types(&self) -> Vec<ObjectRef> {
self.parameters
.iter()
.filter_map(|field| field.ty.dependent_type())
.collect()
}
}
impl Package {