serialization of UStructs/UClasses/AActors
This commit is contained in:
parent
e74ed77703
commit
47dbb8e3d1
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue