// SPDX-FileCopyrightText: 2020 Inseok Lee // SPDX-License-Identifier: MIT #![allow(clippy::bad_bit_mask)] use core::cell::RefCell; use std::collections::HashMap; use std::sync::Arc; use bitflags::bitflags; bitflags! { pub struct HavokValueType: u32 { const EMPTY = 0; const BYTE = 1; const INT = 2; const REAL = 3; const VEC4 = 4; const VEC8 = 5; const VEC12 = 6; const VEC16 = 7; const OBJECT = 8; const STRUCT = 9; const STRING = 10; const ARRAY = 0x10; const ARRAYBYTE = Self::ARRAY.bits | Self::BYTE.bits; const ARRAYINT = Self::ARRAY.bits | Self::INT.bits; const ARRAYREAL = Self::ARRAY.bits | Self::REAL.bits; const ARRAYVEC4 = Self::ARRAY.bits | Self::VEC4.bits; const ARRAYVEC8 = Self::ARRAY.bits | Self::VEC8.bits; const ARRAYVEC12 = Self::ARRAY.bits | Self::VEC12.bits; const ARRAYVEC16 = Self::ARRAY.bits | Self::VEC16.bits; const ARRAYOBJECT = Self::ARRAY.bits | Self::OBJECT.bits; const ARRAYSTRUCT = Self::ARRAY.bits | Self::STRUCT.bits; const ARRAYSTRING = Self::ARRAY.bits | Self::STRING.bits; const TUPLE = 0x20; const TUPLEBYTE = Self::TUPLE.bits | Self::BYTE.bits; const TUPLEINT = Self::TUPLE.bits | Self::INT.bits; const TUPLEREAL = Self::TUPLE.bits | Self::REAL.bits; const TUPLEVEC4 = Self::TUPLE.bits | Self::VEC4.bits; const TUPLEVEC8 = Self::TUPLE.bits | Self::VEC8.bits; const TUPLEVEC12 = Self::TUPLE.bits | Self::VEC12.bits; const TUPLEVEC16 = Self::TUPLE.bits | Self::VEC16.bits; const TUPLEOBJECT = Self::TUPLE.bits | Self::OBJECT.bits; const TUPLESTRUCT = Self::TUPLE.bits | Self::STRUCT.bits; const TUPLESTRING = Self::TUPLE.bits | Self::STRING.bits; } } impl HavokValueType { pub fn is_tuple(self) -> bool { (self.bits & HavokValueType::TUPLE.bits) != 0 } pub fn is_array(self) -> bool { (self.bits & HavokValueType::ARRAY.bits) != 0 } pub fn base_type(self) -> HavokValueType { HavokValueType::from_bits(self.bits & 0x0f).unwrap() } pub fn is_vec(self) -> bool { let base_type = self.base_type(); base_type == HavokValueType::VEC4 || base_type == HavokValueType::VEC8 || base_type == HavokValueType::VEC12 || base_type == HavokValueType::VEC16 } pub fn vec_size(self) -> u8 { match self.base_type() { HavokValueType::VEC4 => 4, HavokValueType::VEC8 => 8, HavokValueType::VEC12 => 12, HavokValueType::VEC16 => 16, _ => panic!(), } } } pub type HavokInteger = i32; pub type HavokReal = f32; pub enum HavokValue { Integer(HavokInteger), Real(HavokReal), String(Arc), Vec(Vec), Array(Vec), Object(Arc>), ObjectReference(usize), } impl HavokValue { pub fn as_int(&self) -> HavokInteger { match self { Self::Integer(x) => *x, _ => panic!(), } } pub fn as_object(&self) -> Arc> { match self { Self::Object(x) => x.clone(), _ => panic!(), } } pub fn as_array(&self) -> &Vec { match self { Self::Array(x) => x, _ => panic!(), } } pub fn as_string(&self) -> &str { match self { Self::String(x) => x, _ => panic!(), } } pub fn as_vec(&self) -> &Vec { match self { Self::Vec(x) => x, _ => panic!(), } } pub fn as_real(&self) -> HavokReal { match self { Self::Real(x) => *x, _ => panic!(), } } } pub struct HavokRootObject { object: Arc>, } impl HavokRootObject { pub fn new(object: Arc>) -> Self { Self { object } } pub fn find_object_by_type(&self, type_name: &'static str) -> Arc> { let root_obj = self.object.borrow(); let named_variants = root_obj.get("namedVariants"); for variant in named_variants.as_array() { let variant_obj = variant.as_object(); if variant_obj.borrow().get("className").as_string() == type_name { return variant_obj.borrow().get("variant").as_object(); } } unreachable!() } } pub struct HavokObjectTypeMember { pub name: Arc, pub type_: HavokValueType, pub tuple_size: u32, pub class_name: Option>, } impl HavokObjectTypeMember { pub fn new(name: Arc, type_: HavokValueType, tuple_size: u32, type_name: Option>) -> Self { Self { name, type_, tuple_size, class_name: type_name, } } } pub struct HavokObjectType { pub name: Arc, parent: Option>, members: Vec, } impl HavokObjectType { pub fn new(name: Arc, parent: Option>, members: Vec) -> Self { Self { name, parent, members } } pub fn members(&self) -> Vec<&HavokObjectTypeMember> { if let Some(x) = &self.parent { x.members().into_iter().chain(self.members.iter()).collect::>() } else { self.members.iter().collect::>() } } pub fn member_count(&self) -> usize { (if let Some(x) = &self.parent { x.members.len() } else { 0 }) + self.members.len() } } pub struct HavokObject { pub object_type: Arc, data: HashMap, } impl HavokObject { pub fn new(object_type: Arc, data: HashMap) -> Self { Self { object_type, data } } pub fn set(&mut self, index: usize, value: HavokValue) { self.data.insert(index, value); } pub fn get(&self, member_name: &str) -> &HavokValue { let member_index = self.object_type.members().iter().position(|&x| &*x.name == member_name).unwrap(); self.data.get(&member_index).unwrap() } pub(crate) fn members_mut(&mut self) -> impl Iterator { self.data.iter_mut() } }