1use std::{
2 ffi::{c_void, CStr, CString},
3 sync::Arc,
4};
5
6use crate::{
7 assembly::Assembly,
8 bindings::{
9 mono_class_get_name, mono_method_desc_new, mono_method_desc_search_in_class,
10 mono_object_new, MonoClass,
11 },
12 domain::Domain,
13 image::Image,
14 method::ClassMethod,
15 object::Object,
16 void::AsRawVoid,
17 MonoResult,
18};
19
20#[derive(Clone, Debug)]
21pub struct Class {
22 pub mono_ptr: *mut MonoClass,
23 pub assembly: Arc<Assembly>,
24 pub domain: Arc<Domain>,
25 pub image: Arc<Image>,
26}
27
28impl Class {
29 pub fn create_object(&self) -> MonoResult<Object> {
30 let mono_ptr = unsafe { mono_object_new(self.domain.mono_ptr, self.mono_ptr) };
31
32 if mono_ptr.is_null() {
33 return Err("MonoObject Null Error!".into());
34 }
35
36 Ok(Object {
37 mono_ptr,
38 assembly: self.assembly.clone(),
39 class: Arc::new(self.clone()),
40 domain: self.domain.clone(),
41 image: self.image.clone(),
42 })
43 }
44
45 pub fn get_name(&self) -> String {
46 unsafe {
47 CStr::from_ptr(mono_class_get_name(self.mono_ptr))
48 .to_string_lossy()
49 .to_string()
50 }
51 }
52
53 pub fn get_method_by_name(&self, name: &'static str) -> MonoResult<ClassMethod> {
54 let class_name = self.get_name();
55 let method_name = CString::new(format!("{}:{}()", class_name, name))?;
56 let mono_method_desc = unsafe { mono_method_desc_new(method_name.as_ptr(), 0) };
57
58 if mono_method_desc.is_null() {
59 return Err("MonoMethodDecs Null Error!".into());
60 }
61
62 let mono_ptr =
63 unsafe { mono_method_desc_search_in_class(mono_method_desc, self.mono_ptr) };
64
65 if mono_ptr.is_null() {
66 return Err("MonoMethod Null Error!".into());
67 }
68
69 Ok(ClassMethod {
70 mono_ptr,
71 assembly: self.assembly.clone(),
72 class: Arc::new(self.clone()),
73 domain: self.domain.clone(),
74 image: self.image.clone(),
75 })
76 }
77}
78
79impl AsRawVoid for Class {
80 fn as_raw_void(self) -> *mut c_void {
81 self.mono_ptr as *mut c_void
82 }
83}