use std::{
mem::transmute,
ops::{Deref, DerefMut},
sync::atomic::AtomicU32,
};
use pelite::pe64::Pe;
use shared::Program;
use vtable_rs::VPtr;
use crate::{
dlkr::DLAllocator,
dltx::{DLString, DLStringError},
dlut::{DLReferenceCountObject, DLReferenceCountObjectVmt, DLReferencePointer},
rva,
};
#[repr(C)]
pub struct EzStateSharedString {
vftable: VPtr<dyn DLReferenceCountObjectVmt, Self>,
reference_count: AtomicU32,
string: DLString,
}
impl EzStateSharedString {
pub fn from_str(
allocator: &'static DLAllocator,
string: &str,
) -> Result<DLReferencePointer<Self>, DLStringError> {
let new = Self {
vftable: unsafe {
transmute::<u64, VPtr<dyn DLReferenceCountObjectVmt, Self>>(
Program::current()
.rva_to_va(rva::get().ez_state_shared_string_vmt)
.unwrap(),
)
},
reference_count: AtomicU32::new(1),
string: DLString::from_str(string, allocator)?,
};
Ok(DLReferencePointer::new(allocator, new))
}
}
impl Deref for EzStateSharedString {
type Target = DLString;
fn deref(&self) -> &Self::Target {
&self.string
}
}
impl DerefMut for EzStateSharedString {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.string
}
}
impl DLReferenceCountObject for EzStateSharedString {
fn vtable(&self) -> VPtr<dyn DLReferenceCountObjectVmt, Self> {
self.vftable
}
fn reference_count(&self) -> &AtomicU32 {
&self.reference_count
}
}