eldenring 0.14.0

Structures, bindings, and utilities for From Software's title Elden Ring
Documentation
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)]
/// A referenced-counted pointer to a DLString used to pass data to and from EzState scripts
///
/// Source of name: RTTI
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
    }
}