mono_rt/types/class.rs
1use super::{
2 MonoClassField, MonoDomain, MonoMethod, MonoObject, MonoType, MonoVTable, mono_handle,
3};
4use crate::{MonoError, Result, api};
5
6use std::ffi::{CStr, CString};
7
8mono_handle!(MonoClass);
9
10impl MonoClass {
11 /// Returns the simple (unqualified) name of this class.
12 ///
13 /// The returned string is copied out of Mono's metadata.
14 ///
15 /// # Errors
16 ///
17 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
18 pub fn name(self) -> Result<String> {
19 let ptr = api()?.class_get_name(self.as_ptr());
20 if ptr.is_null() {
21 return Ok(String::new());
22 }
23
24 Ok(unsafe { CStr::from_ptr(ptr) }
25 .to_string_lossy()
26 .into_owned())
27 }
28
29 /// Looks up a field by name on this class.
30 ///
31 /// # Errors
32 ///
33 /// Returns [`MonoError::NullByteInName`] if `name` contains an interior null byte.
34 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
35 pub fn field(self, name: &str) -> Result<Option<MonoClassField>> {
36 let c_name = CString::new(name).map_err(|_| MonoError::NullByteInName)?;
37 let ptr = api()?.class_get_field_from_name(self.as_ptr(), c_name.as_ptr());
38
39 Ok(MonoClassField::from_ptr(ptr))
40 }
41
42 /// Looks up a method by name on this class.
43 ///
44 /// `param_count` restricts the search to a specific arity; pass `None` to match any overload.
45 ///
46 /// # Errors
47 ///
48 /// Returns [`MonoError::NullByteInName`] if `name` contains an interior null byte.
49 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
50 pub fn method(self, name: &str, param_count: Option<i32>) -> Result<Option<MonoMethod>> {
51 let c_name = CString::new(name).map_err(|_| MonoError::NullByteInName)?;
52 let ptr = api()?.class_get_method_from_name(
53 self.as_ptr(),
54 c_name.as_ptr(),
55 param_count.unwrap_or(-1),
56 );
57 Ok(MonoMethod::from_ptr(ptr))
58 }
59
60 /// Returns the [`MonoType`] descriptor for this class.
61 ///
62 /// # Errors
63 ///
64 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
65 pub fn mono_type(self) -> Result<Option<MonoType>> {
66 let ptr = api()?.class_get_type(self.as_ptr());
67 Ok(MonoType::from_ptr(ptr))
68 }
69
70 /// Returns the vtable for this class in the given domain.
71 ///
72 /// # Errors
73 ///
74 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
75 pub fn vtable(self, domain: MonoDomain) -> Result<Option<MonoVTable>> {
76 let ptr = api()?.class_vtable(domain.as_ptr(), self.as_ptr());
77 Ok(MonoVTable::from_ptr(ptr))
78 }
79
80 /// Allocates a new uninitialized instance of this class in the given domain.
81 ///
82 /// The returned object is not yet constructed — call the `.ctor` method via
83 /// [`MonoMethod::invoke`] to initialize it.
84 ///
85 /// # Errors
86 ///
87 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
88 pub fn new_object(self, domain: MonoDomain) -> Result<Option<MonoObject>> {
89 let ptr = api()?.object_new(domain.as_ptr(), self.as_ptr());
90 Ok(MonoObject::from_ptr(ptr))
91 }
92
93 /// Returns all fields declared on this class.
94 ///
95 /// # Errors
96 ///
97 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
98 pub fn fields(self) -> Result<Vec<MonoClassField>> {
99 Ok(api()?
100 .class_get_fields(self.as_ptr())
101 .into_iter()
102 .filter_map(MonoClassField::from_ptr)
103 .collect())
104 }
105
106 /// Returns all methods declared on this class.
107 ///
108 /// # Errors
109 ///
110 /// Returns [`MonoError::Uninitialized`] if the Mono API has not been initialized.
111 pub fn methods(self) -> Result<Vec<MonoMethod>> {
112 Ok(api()?
113 .class_get_methods(self.as_ptr())
114 .into_iter()
115 .filter_map(MonoMethod::from_ptr)
116 .collect())
117 }
118}