commonlibsse_ng\skse\interfaces/
load.rs1use crate::rel::version::Version;
11use crate::skse::impls::stab::{
12    PluginHandle, PluginInfo, SKSEInterface, SKSEMessagingInterface, SKSEObjectInterface,
13    SKSEPapyrusInterface, SKSEScaleformInterface, SKSESerializationInterface, SKSETaskInterface,
14    SKSETrampolineInterface,
15};
16use crate::skse::interfaces::query::QueryInterface;
17use core::ffi::{CStr, c_void};
18
19#[derive(Debug)]
25#[repr(transparent)]
26pub struct LoadInterface(SKSEInterface);
27
28pub unsafe trait QueryTarget: private::Sealed {
35    #[inline]
40    fn cast(ptr: *mut c_void) -> &'static Self
41    where
42        Self: Sized,
43    {
44        debug_assert!(!ptr.is_null(), "SKSE interface query returned null");
45        unsafe { &*(ptr as *const Self) }
46    }
47
48    const ID: u32;
50}
51
52macro_rules! impl_query_target {
53    ($($t:ty => $id:expr),*) => {
54        $(
55            unsafe impl QueryTarget for $t {
56                const ID: u32 = $id;
57            }
58        )*
59    };
60}
61
62mod private {
64    use super::*;
65
66    pub trait Sealed {}
67    impl Sealed for SKSEScaleformInterface {}
68    impl Sealed for SKSEPapyrusInterface {}
69    impl Sealed for SKSESerializationInterface {}
70    impl Sealed for SKSETaskInterface {}
71    impl Sealed for SKSEMessagingInterface {}
72    impl Sealed for SKSEObjectInterface {}
73    impl Sealed for SKSETrampolineInterface {}
74}
75
76impl_query_target!(
77    SKSEScaleformInterface => 1,
78    SKSEPapyrusInterface => 2,
79    SKSESerializationInterface => 3,
80    SKSETaskInterface => 4,
81    SKSEMessagingInterface => 5,
82    SKSEObjectInterface => 6,
83    SKSETrampolineInterface => 7
84);
85
86impl LoadInterface {
87    #[inline]
89    pub fn get_plugin_handle(&self) -> PluginHandle {
90        unsafe { (self.0.GetPluginHandle)() }
91    }
92
93    #[inline]
97    pub fn get_plugin_info(&self, name: &CStr) -> *const PluginInfo {
98        unsafe { (self.0.GetPluginInfo)(name.as_ptr()) }
99    }
100
101    #[inline]
103    pub fn get_release_index(&self) -> u32 {
104        unsafe { (self.0.GetReleaseIndex)() }
105    }
106
107    #[inline]
109    pub fn query_interface<T: QueryTarget>(&self) -> &'static T {
110        let fn_table = unsafe { (self.0.QueryInterface)(T::ID) };
111        T::cast(fn_table)
112    }
113}
114
115impl QueryInterface for LoadInterface {
116    #[inline]
117    fn editor_version(&self) -> u32 {
118        self.0.editorVersion
119    }
120
121    #[inline]
122    fn is_editor(&self) -> bool {
123        self.0.isEditor != 0
124    }
125
126    #[inline]
127    fn runtime_version(&self) -> Version {
128        let packed = self.0.runtimeVersion;
129        let major = ((packed & 0xFF000000) >> 24) as u16;
130        let minor = ((packed & 0x00FF0000) >> 16) as u16;
131        let revision = ((packed & 0x0000FFF0) >> 4) as u16;
132        let build = (packed & 0x0000000F) as u16;
133        Version::new(major, minor, revision, build)
134    }
135
136    #[inline]
137    fn skse_version(&self) -> u32 {
138        self.0.skseVersion
139    }
140}