1use std::ffi::{CStr, CString};
2use std::ptr;
3
4use super::{MonoClass, mono_handle};
5use crate::{MonoError, Result, api};
6
7struct FindContext<'a> {
8 target_name: &'a str,
9 result: Option<MonoImage>,
10 api_failed: bool,
11}
12
13mono_handle!(MonoImage);
14
15impl MonoImage {
16 pub fn find(name: &str) -> Result<Option<Self>> {
22 let mut ctx = FindContext {
23 target_name: name,
24 result: None,
25 api_failed: false,
26 };
27 api()?.assembly_foreach(find_image_callback, ptr::addr_of_mut!(ctx).cast());
28 if ctx.api_failed {
29 return Err(MonoError::Uninitialized);
30 }
31 Ok(ctx.result)
32 }
33
34 pub fn class_from_name(self, namespace: &str, name: &str) -> Result<Option<MonoClass>> {
41 let ns = CString::new(namespace).map_err(|_| MonoError::NullByteInName)?;
42 let nm = CString::new(name).map_err(|_| MonoError::NullByteInName)?;
43 let ptr = api()?.class_from_name(self.as_ptr(), ns.as_ptr(), nm.as_ptr());
44 Ok(MonoClass::from_ptr(ptr))
45 }
46}
47
48unsafe extern "C" fn find_image_callback(assembly: *mut c_void, user_data: *mut c_void) {
55 let Ok(api) = api() else {
56 let ctx = unsafe { &mut *user_data.cast::<FindContext<'_>>() };
57 ctx.api_failed = true;
58 return;
59 };
60
61 let ctx = unsafe { &mut *user_data.cast::<FindContext<'_>>() };
62 if ctx.result.is_some() {
63 return;
64 }
65
66 let image = api.assembly_get_image(assembly);
67 if image.is_null() {
68 return;
69 }
70
71 let name_ptr = api.image_get_name(image);
72 if name_ptr.is_null() {
73 return;
74 }
75
76 let name = unsafe { CStr::from_ptr(name_ptr) }.to_str().unwrap_or("");
77 if name == ctx.target_name {
78 ctx.result = Some(unsafe { MonoImage::from_ptr_unchecked(image) });
79 }
80}