Skip to main content

il2cpp_bridge_rs/api/wrappers/
application.rs

1//! Thin wrapper around `UnityEngine.Application`.
2//!
3//! These helpers are useful for reading common runtime metadata such as version,
4//! bundle identifier, and persistent data path without repeating method lookup
5//! boilerplate.
6
7use crate::api::{cache, internals::Internals};
8use crate::structs::Il2cppString;
9use std::ffi::c_void;
10
11/// Accessors for selected `UnityEngine.Application` properties.
12pub struct Application;
13
14impl Application {
15    /// Gets the Unity engine version
16    ///
17    /// Returns "unknown" if the version string is empty.
18    pub fn unity_version() -> Result<String, String> {
19        match Self::get_string("get_unityVersion") {
20            Ok(ver) if ver.is_empty() => Ok("unknown".to_string()),
21            Ok(ver) => Ok(ver),
22            Err(e) => Err(e),
23        }
24    }
25
26    /// Gets the application version
27    pub fn version() -> Result<String, String> {
28        Self::get_string("get_version")
29    }
30
31    /// Gets the application identifier (bundle ID)
32    ///
33    /// Tries both `get_identifier` and `get_bundleIdentifier`.
34    pub fn identifier() -> Result<String, String> {
35        let id = Self::get_string("get_identifier");
36        if let Ok(val) = &id {
37            if !val.is_empty() {
38                return id;
39            }
40        }
41        let id = Self::get_string("get_bundleIdentifier");
42        if let Ok(val) = &id {
43            if !val.is_empty() {
44                return id;
45            }
46        }
47        Ok("unknown.application".to_string())
48    }
49
50    /// Gets the persistent data path
51    ///
52    /// Returns the path to a persistent data directory.
53    pub fn data_path() -> Result<String, String> {
54        Self::get_string("get_persistentDataPath")
55    }
56
57    fn get_string(method_name: &str) -> Result<String, String> {
58        let full_name = format!("UnityEngine.Application::{}", method_name);
59
60        let func = Internals::resolve(&full_name);
61        if !func.is_null() {
62            unsafe {
63                let func: extern "C" fn() -> *mut c_void = std::mem::transmute(func);
64                let result = func();
65                if result.is_null() {
66                    return Ok(String::new());
67                }
68                let s = result as *mut Il2cppString;
69                return Ok((*s).to_string().unwrap_or_default());
70            }
71        }
72
73        let klass = cache::coremodule()
74            .class("UnityEngine.Application")
75            .ok_or("Class 'UnityEngine.Application' not found")?;
76
77        let method = klass
78            .method(method_name)
79            .ok_or(format!("Method '{}' not found", method_name))?;
80
81        unsafe {
82            let result: Result<*mut Il2cppString, _> = method.call(&[]);
83            match result {
84                Ok(ptr) => {
85                    if ptr.is_null() {
86                        Ok(String::new())
87                    } else {
88                        Ok((*ptr).to_string().unwrap_or_default())
89                    }
90                }
91                Err(e) => Err(e),
92            }
93        }
94    }
95}