Release 1.1.4

This commit is contained in:
a2x
2023-10-26 15:41:34 +10:00
parent 631668429c
commit 239c872b65
37 changed files with 1905 additions and 1308 deletions

View File

@@ -1,43 +0,0 @@
use std::ffi::c_char;
use std::mem::offset_of;
use anyhow::Result;
use crate::mem::Address;
use crate::remote::Process;
#[derive(Debug)]
#[repr(C)]
pub struct InterfaceReg {
pub create_fn: *const (), // 0x0000
pub name: *const c_char, // 0x0008
pub next: *mut InterfaceReg, // 0x0010
}
impl InterfaceReg {
/// Returns the pointer of the interface.
pub fn pointer(&self, process: &Process) -> Result<Address> {
process
.read_memory::<usize>(
(self as *const _ as usize + offset_of!(InterfaceReg, create_fn)).into(),
)
.map(|ptr| ptr.into())
}
/// Returns the name of the interface.
/// E.g. "Source2Client002"
pub fn name(&self, process: &Process) -> Result<String> {
let name_ptr = process.read_memory::<usize>(
(self as *const _ as usize + offset_of!(InterfaceReg, name)).into(),
)?;
process.read_string(name_ptr.into())
}
/// Returns the next interface in the list.
pub fn next(&self, process: &Process) -> Result<*mut InterfaceReg> {
process.read_memory::<*mut InterfaceReg>(
(self as *const _ as usize + offset_of!(InterfaceReg, next)).into(),
)
}
}

View File

@@ -1,4 +1,3 @@
pub use interface::InterfaceReg;
pub use schema_class_field_data::SchemaClassFieldData;
pub use schema_class_info::SchemaClassInfo;
pub use schema_system::SchemaSystem;
@@ -7,7 +6,6 @@ pub use schema_type::SchemaType;
pub use schema_type_declared_class::SchemaTypeDeclaredClass;
pub use utl_ts_hash::UtlTsHash;
pub mod interface;
pub mod schema_class_field_data;
pub mod schema_class_info;
pub mod schema_system;

View File

@@ -1,40 +1,73 @@
use anyhow::Result;
use crate::mem::Address;
use crate::remote::Process;
use super::SchemaType;
/// Represents a class field in a schema.
use crate::util::{Address, Process};
use anyhow::Result;
/// Represents data for a field in a schema class.
pub struct SchemaClassFieldData<'a> {
process: &'a Process,
/// Address of the class field.
addr: Address,
address: Address,
}
impl<'a> SchemaClassFieldData<'a> {
pub fn new(process: &'a Process, addr: Address) -> Self {
Self { process, addr }
/// Creates a new `SchemaClassFieldData` instance.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
/// * `address` - The address of the `SchemaClassFieldData` instance.
///
/// # Returns
///
/// * `SchemaClassFieldData` - The new `SchemaClassFieldData` instance.
pub fn new(process: &'a Process, address: Address) -> Self {
Self { process, address }
}
/// Returns the name of the field.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaClassFieldData` struct.
///
/// # Returns
///
/// * `Result<String>` - The name of the field.
pub fn name(&self) -> Result<String> {
let name_ptr = self.process.read_memory::<usize>(self.addr + 0x0)?;
let name_ptr = self.process.read_memory::<usize>(self.address)?;
self.process.read_string_len(name_ptr.into(), 64)
self.process.read_string_length(name_ptr.into(), 64)
}
/// Returns the type of the field.
/// Returns the `SchemaType` of the field.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaClassFieldData` struct.
///
/// # Returns
///
/// * `Result<SchemaType>` - The `SchemaType` of the field.
pub fn r#type(&self) -> Result<SchemaType> {
Ok(SchemaType::new(
self.process,
self.process.read_memory::<usize>(self.addr + 0x8)?.into(),
self.process
.read_memory::<usize>(self.address + 0x8)?
.into(),
))
}
/// Returns the offset of the field.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaClassFieldData` struct.
///
/// # Returns
///
/// * `Result<u16>` - The offset of the field.
pub fn offset(&self) -> Result<u16> {
self.process.read_memory::<u16>(self.addr + 0x10)
self.process.read_memory::<u16>(self.address + 0x10)
}
}

View File

@@ -1,47 +1,70 @@
use anyhow::Result;
use crate::mem::Address;
use crate::remote::Process;
use super::SchemaClassFieldData;
/// Represents a class in a schema.
use crate::util::{Address, Process};
use anyhow::Result;
/// Represents information about a schema class.
pub struct SchemaClassInfo<'a> {
process: &'a Process,
/// Address of the class.
addr: Address,
/// Name of the class.
address: Address,
class_name: String,
}
impl<'a> SchemaClassInfo<'a> {
pub fn new(process: &'a Process, addr: Address, class_name: &str) -> Self {
/// Creates a new `SchemaClassInfo` instance.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
/// * `address` - The address of the `SchemaClassInfo` instance.
/// * `class_name` - The name of the class.
///
/// # Returns
///
/// * `SchemaClassInfo` - The new `SchemaClassInfo` instance.
pub fn new(process: &'a Process, address: Address, class_name: &str) -> Self {
Self {
process,
addr,
address,
class_name: class_name.to_string(),
}
}
/// Returns the name of the class.
/// Returns a reference to the name of the class.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaClassInfo` struct.
///
/// # Returns
///
/// * `&str` - A string slice containing the name of the class.
#[inline]
pub fn name(&self) -> &str {
&self.class_name
}
/// Returns a list of fields in the class.
/// Returns a vector of `SchemaClassFieldData` representing the fields of the schema class.
/// If the address of the schema class is null, an empty vector is returned.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaClassInfo` struct.
///
/// # Returns
///
/// * `Result<Vec<SchemaClassFieldData>>` - A vector of `SchemaClassFieldData` representing the fields of the schema class.
pub fn fields(&self) -> Result<Vec<SchemaClassFieldData>> {
let addr = self.process.read_memory::<usize>(self.addr + 0x28)?;
let address = self.process.read_memory::<usize>(self.address + 0x28)?;
if addr == 0 {
if address == 0 {
return Ok(Vec::new());
}
let count = self.fields_count()?;
let fields: Vec<SchemaClassFieldData> = (addr..addr + count as usize * 0x20)
let fields: Vec<SchemaClassFieldData> = (address..address + count as usize * 0x20)
.step_by(0x20)
.map(|address| SchemaClassFieldData::new(self.process, address.into()))
.collect();
@@ -50,21 +73,38 @@ impl<'a> SchemaClassInfo<'a> {
}
/// Returns the number of fields in the class.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaClassInfo` struct.
///
/// # Returns
///
/// * `Result<u16>` - The number of fields in the class.
pub fn fields_count(&self) -> Result<u16> {
self.process.read_memory::<u16>(self.addr + 0x1C)
self.process.read_memory::<u16>(self.address + 0x1C)
}
/// Returns the parent class.
/// Returns the parent `SchemaClassInfo` of the current `SchemaClassInfo` instance.
/// If the parent is not found, returns `Ok(None)`.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaClassInfo` struct.
///
/// # Returns
///
/// * `Result<Option<SchemaClassInfo>>` - The parent `SchemaClassInfo` of the current `SchemaClassInfo` instance.
pub fn parent(&self) -> Result<Option<SchemaClassInfo>> {
let addr = self.process.read_memory::<usize>(self.addr + 0x38)?;
let address = Address::from(self.process.read_memory::<usize>(self.address + 0x38)?);
if addr == 0 {
if address.is_zero() {
return Ok(None);
}
let parent = self.process.read_memory::<usize>((addr + 0x8).into())?;
let parent = Address::from(self.process.read_memory::<usize>(address + 0x8)?);
let name_ptr = self.process.read_memory::<usize>((parent + 0x8).into())?;
let name_ptr = self.process.read_memory::<usize>(parent + 0x8)?;
let name = self.process.read_string(name_ptr.into())?;
Ok(Some(SchemaClassInfo::new(

View File

@@ -1,43 +1,57 @@
use std::mem;
use super::SchemaSystemTypeScope;
use crate::util::{Address, Process};
use anyhow::{bail, Result};
use crate::mem::Address;
use crate::remote::Process;
use super::SchemaSystemTypeScope;
use std::mem;
/// Represents the schema system.
pub struct SchemaSystem<'a> {
process: &'a Process,
/// Address of the schema system.
addr: Address,
address: Address,
}
impl<'a> SchemaSystem<'a> {
/// Creates a new `SchemaSystem` instance.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
///
/// # Returns
///
/// * `Result<SchemaSystem>` - The new `SchemaSystem` instance.
pub fn new(process: &'a Process) -> Result<Self> {
let mut addr = process.find_pattern(
let mut address = process.find_pattern(
"schemasystem.dll",
"48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 83 EC 28"
)?;
).expect("Failed to find SchemaSystem pattern");
addr = process.resolve_rip(addr, None, None)?;
address = process.resolve_rip(address, 0x3, 0x7)?;
Ok(Self { process, addr })
Ok(Self { process, address })
}
/// Returns a list of type scopes.
/// Returns a vector of `SchemaSystemTypeScope` objects.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaSystem` struct.
///
/// # Returns
///
/// * `Result<Vec<SchemaSystemTypeScope>>` - A vector of `SchemaSystemTypeScope` objects.
pub fn type_scopes(&self) -> Result<Vec<SchemaSystemTypeScope>> {
let size = self.process.read_memory::<u32>(self.addr + 0x190)?;
let size = self.process.read_memory::<u32>(self.address + 0x190)?;
if size == 0 {
bail!("Type scopes size is 0");
}
let data = self.process.read_memory::<usize>(self.addr + 0x198)?;
let data = self.process.read_memory::<usize>(self.address + 0x198)?;
let mut addresses: Vec<usize> = vec![0; size as usize];
let mut addresses = vec![0; size as usize];
self.process.read_memory_raw(
data.into(),
@@ -47,7 +61,7 @@ impl<'a> SchemaSystem<'a> {
let type_scopes: Vec<SchemaSystemTypeScope> = addresses
.iter()
.map(|&addr| SchemaSystemTypeScope::new(self.process, addr.into()))
.map(|&address| SchemaSystemTypeScope::new(self.process, address.into()))
.collect();
Ok(type_scopes)

View File

@@ -1,49 +1,73 @@
use anyhow::Result;
use crate::mem::Address;
use crate::remote::Process;
use super::{SchemaClassInfo, SchemaTypeDeclaredClass, UtlTsHash};
/// Represents a schema system type scope.
use crate::util::{Address, Process};
use anyhow::Result;
/// Represents a system type scope in the schema.
pub struct SchemaSystemTypeScope<'a> {
process: &'a Process,
/// Address of the schema system type scope.
addr: Address,
address: Address,
}
impl<'a> SchemaSystemTypeScope<'a> {
pub fn new(process: &'a Process, addr: Address) -> Self {
Self { process, addr }
/// Creates a new `SchemaSystemTypeScope` instance.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
/// * `address` - The address of the `SchemaSystemTypeScope` instance.
/// * `class_name` - The name of the class.
///
/// # Returns
///
/// * `SchemaSystemTypeScope` - The new `SchemaSystemTypeScope` instance.
pub fn new(process: &'a Process, address: Address) -> Self {
Self { process, address }
}
/// Returns a list of classes in the type scope.
/// Returns a vector of `SchemaClassInfo` containing information about all the classes declared in the current scope.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaSystemTypeScope` struct.
///
/// # Returns
///
/// * `Result<Vec<SchemaClassInfo>>` - A vector of `SchemaClassInfo` containing information about all the classes declared in the current scope.
pub fn classes(&self) -> Result<Vec<SchemaClassInfo>> {
let declared_classes = self
.process
.read_memory::<UtlTsHash<*mut SchemaTypeDeclaredClass>>(self.addr + 0x588)?;
.read_memory::<UtlTsHash<*mut SchemaTypeDeclaredClass>>(self.address + 0x588)?;
let classes: Vec<SchemaClassInfo> = declared_classes
.elements(self.process)?
.iter()
.filter_map(|&addr| {
let addr = Address::from(addr as usize);
.filter_map(|&a| {
let address = Address::from(a as usize);
let declared_class = SchemaTypeDeclaredClass::new(self.process, addr);
let declared_class = SchemaTypeDeclaredClass::new(self.process, address);
declared_class
.name()
.ok()
.map(|name| SchemaClassInfo::new(self.process, addr, &name))
.map(|name| SchemaClassInfo::new(self.process, address, &name))
})
.collect();
Ok(classes)
}
/// Returns the name of the module that the type scope belongs to.
/// Returns the name of the module associated with the current `SchemaSystemTypeScope` instance.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaSystemTypeScope` struct.
///
/// # Returns
///
/// * `Result<String>` - The name of the module associated with the current `SchemaSystemTypeScope` instance.
pub fn module_name(&self) -> Result<String> {
self.process.read_string_len(self.addr + 0x8, 256)
self.process.read_string_length(self.address + 0x8, 256)
}
}

View File

@@ -1,4 +1,4 @@
use std::collections::HashMap;
use crate::util::{Address, Process};
use anyhow::Result;
@@ -6,10 +6,9 @@ use lazy_static::lazy_static;
use regex::Regex;
use crate::mem::Address;
use crate::remote::Process;
use std::collections::HashMap;
/// Map of type names to their C equivalents.
/// Map of type names to their `C` equivalents.
const TYPE_MAP: &[(&'static str, &'static str)] = &[
("uint8", "uint8_t"),
("uint16", "uint16_t"),
@@ -24,6 +23,8 @@ const TYPE_MAP: &[(&'static str, &'static str)] = &[
];
lazy_static! {
/// A static HashMap that maps a string to a Regex pattern.
/// The Regex pattern is created by wrapping the string with word boundaries `(\b)`.
static ref REGEX_MAP: HashMap<&'static str, Regex> = {
let mut map = HashMap::with_capacity(TYPE_MAP.len());
@@ -35,22 +36,38 @@ lazy_static! {
};
}
/// Represents a schema type.
/// Represents a type in the schema.
pub struct SchemaType<'a> {
process: &'a Process,
/// Address of the schema type.
addr: Address,
address: Address,
}
impl<'a> SchemaType<'a> {
pub fn new(process: &'a Process, addr: Address) -> Self {
Self { process, addr }
/// Creates a new `SchemaType` instance.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
/// * `address` - The address of the `SchemaType` instance.
///
/// # Returns
///
/// * `SchemaType` - The new `SchemaType` instance.
pub fn new(process: &'a Process, address: Address) -> Self {
Self { process, address }
}
/// Returns the name of the type.
/// Returns the name of the schema type.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaType` instance.
///
/// # Returns
///
/// * `Result<String>` - The name of the schema type, wrapped in a `Result` object.
pub fn name(&self) -> Result<String> {
let name_ptr = self.process.read_memory::<usize>(self.addr + 0x8)?;
let name_ptr = self.process.read_memory::<usize>(self.address + 0x8)?;
let name = self
.process
@@ -61,6 +78,15 @@ impl<'a> SchemaType<'a> {
Ok(Self::convert_type_name(&name))
}
/// Converts a schema type name to its `C` equivalent.
///
/// # Arguments
///
/// * `type_name` - A string slice that holds the name of the schema type.
///
/// # Returns
///
/// * `String` - The `C` equivalent of the schema type name.
fn convert_type_name(type_name: &str) -> String {
let mut result = type_name.to_string();

View File

@@ -1,25 +1,40 @@
use crate::util::{Address, Process};
use anyhow::Result;
use crate::mem::Address;
use crate::remote::Process;
/// Represents a schema type declared class.
/// Represents a declared class type in the schema.
pub struct SchemaTypeDeclaredClass<'a> {
process: &'a Process,
/// Address of the schema type declared class.
addr: Address,
address: Address,
}
impl<'a> SchemaTypeDeclaredClass<'a> {
pub fn new(process: &'a Process, addr: Address) -> Self {
Self { process, addr }
/// Creates a new `SchemaTypeDeclaredClass` instance.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
/// * `address` - The address of the `SchemaTypeDeclaredClass` instance.
///
/// # Returns
///
/// * `SchemaTypeDeclaredClass` - The new `SchemaTypeDeclaredClass` instance.
pub fn new(process: &'a Process, address: Address) -> Self {
Self { process, address }
}
/// Returns the name of the class.
/// Returns the name of the declared class.
///
/// # Arguments
///
/// * `&self` - A reference to the `SchemaTypeDeclaredClass` struct.
///
/// # Returns
///
/// * `Result<String>` - The name of the declared class.
pub fn name(&self) -> Result<String> {
let name_ptr = self.process.read_memory::<usize>(self.addr + 0x8)?;
let name_ptr = self.process.read_memory::<usize>(self.address + 0x8)?;
self.process.read_string_len(name_ptr.into(), 64)
self.process.read_string_length(name_ptr.into(), 64)
}
}

View File

@@ -1,44 +1,63 @@
use crate::util::Process;
use anyhow::Result;
use std::mem::offset_of;
use crate::remote::Process;
/// Represents a hash bucket.
/// Represents the internal data of a hash table.
#[derive(Debug)]
#[repr(C)]
pub struct HashFixedDataInternal<T, K> {
struct HashFixedDataInternal<T, K> {
ui_key: K, // 0x0010
next: *mut HashFixedDataInternal<T, K>, // 0x0010
data: T, // 0x0010
}
/// Implementation of HashFixedDataInternal struct with methods for reading the next element in the hash table.
impl<T, K> HashFixedDataInternal<T, K> {
pub fn next(&self, process: &Process) -> Result<*mut HashFixedDataInternal<T, K>> {
/// Reads the next element in the hash table.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
///
/// # Returns
///
/// Returns a Result containing a pointer to the next element in the hash table if successful, or an error if unsuccessful.
fn next(&self, process: &Process) -> Result<*mut HashFixedDataInternal<T, K>> {
process.read_memory::<*mut HashFixedDataInternal<T, K>>(
(self as *const _ as usize + offset_of!(HashFixedDataInternal<T, K>, next)).into(),
)
}
}
/// Represents a hash bucket.
/// Represents the internal data of a hash bucket.
#[derive(Debug)]
#[repr(C)]
pub struct HashBucketDataInternal<T, K> {
struct HashBucketDataInternal<T, K> {
data: T, // 0x0000
next: *mut HashFixedDataInternal<T, K>, // 0x0008
ui_key: K, // 0x0010
}
impl<T, K> HashBucketDataInternal<T, K> {
pub fn next(&self, process: &Process) -> Result<*mut HashFixedDataInternal<T, K>> {
/// Reads the next element in the hash table.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
///
/// # Returns
///
/// Returns a Result containing a pointer to the next element in the hash table if successful, or an error if unsuccessful.
fn next(&self, process: &Process) -> Result<*mut HashFixedDataInternal<T, K>> {
process.read_memory::<*mut HashFixedDataInternal<T, K>>(
(self as *const _ as usize + offset_of!(HashBucketDataInternal<T, K>, next)).into(),
)
}
}
/// Represents a hash table.
/// Represents allocated data in a hash table.
#[derive(Debug)]
#[repr(C)]
pub struct HashAllocatedData<T, K> {
@@ -47,17 +66,26 @@ pub struct HashAllocatedData<T, K> {
}
impl<T, K> HashAllocatedData<T, K> {
pub fn list(&self, process: &Process) -> Result<[HashFixedDataInternal<T, K>; 128]> {
/// Reads the list of elements in the hash table.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
///
/// # Returns
///
/// Returns a Result containing a list of elements in the hash table if successful, or an error if unsuccessful.
fn list(&self, process: &Process) -> Result<[HashFixedDataInternal<T, K>; 128]> {
process.read_memory::<[HashFixedDataInternal<T, K>; 128]>(
(self as *const _ as usize + offset_of!(HashAllocatedData<T, K>, list)).into(),
)
}
}
/// Represents a hash table.
/// A struct representing unallocated data in a hash table.
#[derive(Debug)]
#[repr(C)]
pub struct HashUnallocatedData<T, K> {
struct HashUnallocatedData<T, K> {
next: *mut HashUnallocatedData<T, K>, // 0x0000
unknown_1: K, // 0x0008
ui_key: K, // 0x0010
@@ -66,19 +94,46 @@ pub struct HashUnallocatedData<T, K> {
}
impl<T, K> HashUnallocatedData<T, K> {
pub fn next(&self, process: &Process) -> Result<*mut HashUnallocatedData<T, K>> {
/// Reads the next `HashUnallocatedData` element in memory.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
///
/// # Returns
///
/// * `Result<*mut HashUnallocatedData<T, K>>` - A Result containing a pointer to the next `HashUnallocatedData` element in memory.
fn next(&self, process: &Process) -> Result<*mut HashUnallocatedData<T, K>> {
process.read_memory::<*mut HashUnallocatedData<T, K>>(
(self as *const _ as usize + offset_of!(HashUnallocatedData<T, K>, next)).into(),
)
}
pub fn ui_key(&self, process: &Process) -> Result<K> {
/// Reads the UI key of the `HashUnallocatedData` element in memory.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
///
/// # Returns
///
/// * `Result<K>` - A Result containing the UI key of the `HashUnallocatedData` element in memory.
fn ui_key(&self, process: &Process) -> Result<K> {
process.read_memory::<K>(
(self as *const _ as usize + offset_of!(HashUnallocatedData<T, K>, ui_key)).into(),
)
}
pub fn block_list(&self, process: &Process) -> Result<[HashBucketDataInternal<T, K>; 256]> {
/// Reads the block list of the `HashUnallocatedData` element in memory.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
///
/// # Returns
///
/// * `Result<[HashBucketDataInternal<T, K>; 256]>` - A Result containing the block list of the `HashUnallocatedData` element in memory.
fn block_list(&self, process: &Process) -> Result<[HashBucketDataInternal<T, K>; 256]> {
process.read_memory::<[HashBucketDataInternal<T, K>; 256]>(
(self as *const _ as usize + offset_of!(HashUnallocatedData<T, K>, block_list)).into(),
)
@@ -88,15 +143,16 @@ impl<T, K> HashUnallocatedData<T, K> {
/// Represents a hash bucket.
#[derive(Debug)]
#[repr(C)]
pub struct HashBucket<T, K> {
struct HashBucket<T, K> {
pad_0: [u8; 0x10], // 0x0000
allocated_data: *const HashAllocatedData<T, K>, // 0x0010
unallocated_data: *const HashUnallocatedData<T, K>, // 0x0018
}
/// Represents a memory pool used by the `UtlTsHash` class.
#[derive(Debug)]
#[repr(C)]
pub struct UtlMemoryPool {
struct UtlMemoryPool {
block_size: i32, // 0x0000
blocks_per_blob: i32, // 0x0004
grow_mode: i32, // 0x0008
@@ -107,14 +163,30 @@ pub struct UtlMemoryPool {
impl UtlMemoryPool {
/// Returns the number of blocks per blob.
///
/// # Arguments
///
/// * `&self` - A reference to the `UtlMemoryPool` struct.
///
/// # Returns
///
/// * `i32` - The number of blocks per blob.
#[inline]
pub fn block_size(&self) -> i32 {
fn block_size(&self) -> i32 {
self.blocks_per_blob
}
/// Returns the number of blocks allocated.
///
/// # Arguments
///
/// * `&self` - A reference to the `UtlMemoryPool` struct.
///
/// # Returns
///
/// * `i32` - The number of blocks allocated.
#[inline]
pub fn count(&self) -> i32 {
fn count(&self) -> i32 {
self.block_allocated_size
}
}
@@ -132,25 +204,49 @@ where
T: Copy,
{
/// Returns the number of blocks per blob.
///
/// # Arguments
///
/// * `&self` - A reference to the `UtlTsHash` struct.
///
/// # Returns
///
/// * `i32` - The number of blocks per blob.
#[inline]
pub fn block_size(&self) -> i32 {
self.entry_memory.block_size()
}
/// Returns the number of blocks allocated.
///
/// # Arguments
///
/// * `&self` - A reference to the `UtlTsHash` struct.
///
/// # Returns
///
/// * `i32` - The number of blocks allocated.
#[inline]
pub fn count(&self) -> i32 {
self.entry_memory.count()
}
/// Returns a list of elements in the hash table.
///
/// # Arguments
///
/// * `process` - A reference to the `Process` struct.
///
/// # Returns
///
/// * `Result<Vec<T>>` - A Result containing a list of elements in the hash table if successful, or an error if unsuccessful.
pub fn elements(&self, process: &Process) -> Result<Vec<T>> {
let mut address = self.buckets.unallocated_data;
let min_size = (self.block_size() as usize).min(self.count() as usize);
let mut list = Vec::with_capacity(min_size);
let mut address = self.buckets.unallocated_data;
while !address.is_null() {
let block_list = unsafe { (*address).block_list(process) }?;