diff --git a/.gitmodules b/.gitmodules
index 6cd1abf41..a694cec89 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "crates/mun_abi/c"]
path = crates/mun_abi/c
url = ../../mun-lang/abi-c
+[submodule "crates/mun_runtime_capi/c"]
+ path = crates/mun_runtime_capi/c
+ url = ../../mun-lang/runtime-c.git
diff --git a/crates/mun_abi/build.rs b/crates/mun_abi/build.rs
index 7939d166c..f002e1c7f 100644
--- a/crates/mun_abi/build.rs
+++ b/crates/mun_abi/build.rs
@@ -35,12 +35,14 @@ fn main() {
.whitelist_type("Mun.*")
.blacklist_type("MunPrivacy.*")
.parse_callbacks(Box::new(RemoveVendorName))
+ .raw_line("#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]")
+ .raw_line("use crate::Privacy;")
.generate()
.expect("Unable to generate bindings for 'mun_abi.h'");
- let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
+ let out_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
bindings
- .write_to_file(out_path.join("bindings.rs"))
+ .write_to_file(out_path.join("src/autogen.rs"))
.expect(&format!(
"Couldn't write bindings to '{}'",
out_path.as_path().to_string_lossy()
diff --git a/crates/mun_abi/src/autogen.rs b/crates/mun_abi/src/autogen.rs
index d5b3dc207..7e780a1d2 100644
--- a/crates/mun_abi/src/autogen.rs
+++ b/crates/mun_abi/src/autogen.rs
@@ -1,563 +1,342 @@
-#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
-
-use crate::prelude::*;
+/* automatically generated by rust-bindgen */
-include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
-
-use std::ffi::{c_void, CStr};
-use std::slice;
+#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
+use crate::Privacy;
-impl TypeInfo {
- /// Returns the type's name.
- pub fn name(&self) -> &str {
- unsafe { CStr::from_ptr(self.name) }
- .to_str()
- .expect("Type name contains invalid UTF8")
- }
+#[doc = "
"]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub struct Guid {
+ pub b: [u8; 16usize],
}
-
-impl PartialEq for TypeInfo {
- fn eq(&self, other: &Self) -> bool {
- self.guid == other.guid
- }
+#[test]
+fn bindgen_test_layout_Guid() {
+ assert_eq!(
+ ::std::mem::size_of::
(),
+ 16usize,
+ concat!("Size of: ", stringify!(Guid))
+ );
+ assert_eq!(
+ ::std::mem::align_of::(),
+ 1usize,
+ concat!("Alignment of ", stringify!(Guid))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).b as *const _ as usize },
+ 0usize,
+ concat!("Offset of field: ", stringify!(Guid), "::", stringify!(b))
+ );
}
-
-impl FunctionSignature {
- /// Returns the function's name.
- pub fn name(&self) -> &str {
- unsafe { CStr::from_ptr(self.name) }
- .to_str()
- .expect("Function name contains invalid UTF8")
- }
-
- /// Returns the function's privacy level.
- pub fn privacy(&self) -> Privacy {
- self.privacy
- }
-
- /// Returns the function's arguments' types.
- pub fn arg_types(&self) -> &[TypeInfo] {
- if self.num_arg_types == 0 {
- &[]
- } else {
- unsafe { slice::from_raw_parts(self.arg_types, self.num_arg_types as usize) }
- }
- }
-
- /// Returns the function's return type
- pub fn return_type(&self) -> Option<&TypeInfo> {
- unsafe { self.return_type.as_ref() }
- }
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct TypeInfo {
+ pub guid: Guid,
+ pub name: *const ::std::os::raw::c_char,
}
-
-impl ModuleInfo {
- /// Returns the module's full path.
- pub fn path(&self) -> &str {
- unsafe { CStr::from_ptr(self.path) }
- .to_str()
- .expect("Module path contains invalid UTF8")
- }
-
- // /// Finds the type's fields that match `filter`.
- // pub fn find_fields(&self, filter: fn(&&FieldInfo) -> bool) -> impl Iterator- {
- // self.fields.iter().map(|f| *f).filter(filter)
- // }
-
- // /// Retrieves the type's field with the specified `name`, if it exists.
- // pub fn get_field(&self, name: &str) -> Option<&FieldInfo> {
- // self.fields.iter().find(|f| f.name == name).map(|f| *f)
- // }
-
- // /// Retrieves the type's fields.
- // pub fn get_fields(&self) -> impl Iterator
- {
- // self.fields.iter().map(|f| *f)
- // }
-
- /// Returns the module's functions.
- pub fn functions(&self) -> &[FunctionInfo] {
- if self.num_functions == 0 {
- &[]
- } else {
- unsafe { slice::from_raw_parts(self.functions, self.num_functions as usize) }
- }
- }
+#[test]
+fn bindgen_test_layout_TypeInfo() {
+ assert_eq!(
+ ::std::mem::size_of::(),
+ 24usize,
+ concat!("Size of: ", stringify!(TypeInfo))
+ );
+ assert_eq!(
+ ::std::mem::align_of::(),
+ 8usize,
+ concat!("Alignment of ", stringify!(TypeInfo))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).guid as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(TypeInfo),
+ "::",
+ stringify!(guid)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).name as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(TypeInfo),
+ "::",
+ stringify!(name)
+ )
+ );
}
-
-impl DispatchTable {
- /// Returns an iterator over pairs of mutable function pointers and signatures.
- pub fn iter_mut(&mut self) -> impl Iterator
- {
- if self.num_entries == 0 {
- (&mut []).iter_mut().zip((&[]).iter())
- } else {
- let ptrs =
- unsafe { slice::from_raw_parts_mut(self.fn_ptrs, self.num_entries as usize) };
- let signatures =
- unsafe { slice::from_raw_parts(self.signatures, self.num_entries as usize) };
-
- ptrs.iter_mut().zip(signatures.iter())
- }
- }
-
- /// Returns mutable functions pointers.
- pub fn ptrs_mut(&mut self) -> &mut [*const c_void] {
- if self.num_entries == 0 {
- &mut []
- } else {
- unsafe { slice::from_raw_parts_mut(self.fn_ptrs, self.num_entries as usize) }
- }
- }
-
- /// Returns function signatures.
- pub fn signatures(&self) -> &[FunctionSignature] {
- if self.num_entries == 0 {
- &[]
- } else {
- unsafe { slice::from_raw_parts(self.signatures, self.num_entries as usize) }
- }
- }
-
- /// Returns a function pointer, without doing bounds checking.
- ///
- /// This is generally not recommended, use with caution! Calling this method with an
- /// out-of-bounds index is _undefined behavior_ even if the resulting reference is not used.
- /// For a safe alternative see [get_ptr](#method.get_ptr).
- pub unsafe fn get_ptr_unchecked(&self, idx: u32) -> *const c_void {
- *self.fn_ptrs.offset(idx as isize)
- }
-
- /// Returns a function pointer at the given index, or `None` if out of bounds.
- pub fn get_ptr(&self, idx: u32) -> Option<*const c_void> {
- if idx < self.num_entries {
- Some(unsafe { self.get_ptr_unchecked(idx) })
- } else {
- None
- }
- }
-
- /// Returns a mutable reference to a function pointer, without doing bounds checking.
- ///
- /// This is generally not recommended, use with caution! Calling this method with an
- /// out-of-bounds index is _undefined behavior_ even if the resulting reference is not used.
- /// For a safe alternative see [get_ptr_mut](#method.get_ptr_mut).
- pub unsafe fn get_ptr_unchecked_mut(&self, idx: u32) -> &mut *const c_void {
- &mut *self.fn_ptrs.offset(idx as isize)
- }
-
- /// Returns a mutable reference to a function pointer at the given index, or `None` if out of
- /// bounds.
- pub fn get_ptr_mut(&self, idx: u32) -> Option<&mut *const c_void> {
- if idx < self.num_entries {
- Some(unsafe { self.get_ptr_unchecked_mut(idx) })
- } else {
- None
- }
- }
+#[doc = "
"]
+#[repr(C)]
+#[derive(Clone)]
+pub struct FunctionSignature {
+ pub name: *const ::std::os::raw::c_char,
+ pub arg_types: *const TypeInfo,
+ pub return_type: *const TypeInfo,
+ pub num_arg_types: u16,
+ pub privacy: Privacy,
}
-
-impl AssemblyInfo {
- /// Returns an iterator over the assembly's dependencies.
- pub fn dependencies(&self) -> impl Iterator
- {
- let dependencies = if self.num_dependencies == 0 {
- &[]
- } else {
- unsafe { slice::from_raw_parts(self.dependencies, self.num_dependencies as usize) }
- };
-
- dependencies.iter().map(|d| {
- unsafe { CStr::from_ptr(*d) }
- .to_str()
- .expect("dependency path contains invalid UTF8")
- })
- }
+#[test]
+fn bindgen_test_layout_FunctionSignature() {
+ assert_eq!(
+ ::std::mem::size_of::(),
+ 32usize,
+ concat!("Size of: ", stringify!(FunctionSignature))
+ );
+ assert_eq!(
+ ::std::mem::align_of::(),
+ 8usize,
+ concat!("Alignment of ", stringify!(FunctionSignature))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).name as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(FunctionSignature),
+ "::",
+ stringify!(name)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).arg_types as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(FunctionSignature),
+ "::",
+ stringify!(arg_types)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).return_type as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(FunctionSignature),
+ "::",
+ stringify!(return_type)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).num_arg_types as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(FunctionSignature),
+ "::",
+ stringify!(num_arg_types)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).privacy as *const _ as usize },
+ 26usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(FunctionSignature),
+ "::",
+ stringify!(privacy)
+ )
+ );
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use std::ffi::CString;
- use std::os::raw::c_char;
- use std::ptr;
-
- fn fake_type_info(name: &CStr) -> TypeInfo {
- TypeInfo {
- guid: FAKE_TYPE_GUID,
- name: name.as_ptr(),
- }
- }
-
- const FAKE_TYPE_GUID: Guid = Guid {
- b: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
- };
-
- const FAKE_TYPE_NAME: &'static str = "type-name";
-
- #[test]
- fn test_type_info_name() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- assert_eq!(type_info.name(), FAKE_TYPE_NAME);
- }
-
- #[test]
- fn test_type_info_eq() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- assert_eq!(type_info, type_info);
- }
-
- fn fake_fn_signature(
- name: &CStr,
- arg_types: &[TypeInfo],
- return_type: Option<&TypeInfo>,
- privacy: Privacy,
- ) -> FunctionSignature {
- FunctionSignature {
- name: name.as_ptr(),
- arg_types: arg_types.as_ptr(),
- return_type: return_type.map_or(ptr::null(), |t| t as *const TypeInfo),
- num_arg_types: arg_types.len() as u16,
- privacy,
- }
- }
-
- const FAKE_FN_NAME: &'static str = "fn-name";
-
- #[test]
- fn test_fn_signature_name() {
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], None, Privacy::Public);
-
- assert_eq!(fn_signature.name(), FAKE_FN_NAME);
- }
-
- #[test]
- fn test_fn_signature_privacy() {
- let privacy = Privacy::Private;
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], None, privacy);
-
- assert_eq!(fn_signature.privacy(), privacy);
- }
-
- #[test]
- fn test_fn_signature_arg_types_none() {
- let arg_types = &[];
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, arg_types, None, Privacy::Public);
-
- assert_eq!(fn_signature.arg_types(), arg_types);
- }
-
- #[test]
- fn test_fn_signature_arg_types_some() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let arg_types = &[type_info];
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, arg_types, None, Privacy::Public);
-
- assert_eq!(fn_signature.arg_types(), arg_types);
- }
-
- #[test]
- fn test_fn_signature_return_type_none() {
- let return_type = None;
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- assert_eq!(fn_signature.return_type(), return_type);
- }
-
- #[test]
- fn test_fn_signature_return_type_some() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- assert_eq!(fn_signature.return_type(), return_type);
- }
-
- fn fake_module_info(path: &CStr, functions: &[FunctionInfo]) -> ModuleInfo {
- ModuleInfo {
- path: path.as_ptr(),
- functions: functions.as_ptr(),
- num_functions: functions.len() as u32,
- }
- }
-
- const FAKE_MODULE_PATH: &'static str = "path::to::module";
-
- #[test]
- fn test_module_info_path() {
- let module_path = CString::new(FAKE_MODULE_PATH).expect("Invalid fake module path.");
- let module = fake_module_info(&module_path, &[]);
-
- assert_eq!(module.path(), FAKE_MODULE_PATH);
- }
-
- #[test]
- fn test_module_info_functions_none() {
- let functions = &[];
- let module_path = CString::new(FAKE_MODULE_PATH).expect("Invalid fake module path.");
- let module = fake_module_info(&module_path, functions);
-
- assert_eq!(module.functions().len(), functions.len());
- }
-
- #[test]
- fn test_module_info_functions_some() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- let fn_info = FunctionInfo {
- signature: fn_signature,
- fn_ptr: ptr::null(),
- };
-
- let functions = &[fn_info];
- let module_path = CString::new(FAKE_MODULE_PATH).expect("Invalid fake module path.");
- let module = fake_module_info(&module_path, functions);
-
- let result = module.functions();
- assert_eq!(result.len(), functions.len());
- for (lhs, rhs) in result.iter().zip(functions.iter()) {
- assert_eq!(lhs.fn_ptr, rhs.fn_ptr);
- assert_eq!(lhs.signature.name(), rhs.signature.name());
- assert_eq!(lhs.signature.arg_types(), rhs.signature.arg_types());
- assert_eq!(lhs.signature.return_type(), rhs.signature.return_type());
- assert_eq!(lhs.signature.privacy(), rhs.signature.privacy());
- }
- }
-
- fn fake_dispatch_table(
- fn_signatures: &[FunctionSignature],
- fn_ptrs: &mut [*const c_void],
- ) -> DispatchTable {
- assert!(fn_signatures.len() == fn_ptrs.len());
-
- DispatchTable {
- signatures: fn_signatures.as_ptr(),
- fn_ptrs: fn_ptrs.as_mut_ptr(),
- num_entries: fn_signatures.len() as u32,
- }
- }
-
- #[test]
- fn test_dispatch_table_iter_mut_none() {
- let signatures = &[];
- let fn_ptrs = &mut [];
- let mut dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
-
- let iter = fn_ptrs.iter_mut().zip(signatures.iter());
- assert_eq!(dispatch_table.iter_mut().count(), iter.count());
- }
-
- #[test]
- fn test_dispatch_table_iter_mut_some() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- let signatures = &[fn_signature];
- let fn_ptrs = &mut [ptr::null()];
- let mut dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
-
- let iter = fn_ptrs.iter_mut().zip(signatures.iter());
- assert_eq!(dispatch_table.iter_mut().count(), iter.len());
-
- for (lhs, rhs) in dispatch_table.iter_mut().zip(iter) {
- assert_eq!(lhs.0, rhs.0);
- assert_eq!(lhs.1.name(), rhs.1.name());
- assert_eq!(lhs.1.arg_types(), rhs.1.arg_types());
- assert_eq!(lhs.1.return_type(), rhs.1.return_type());
- assert_eq!(lhs.1.privacy(), rhs.1.privacy());
- }
- }
-
- #[test]
- fn test_dispatch_table_ptrs_mut() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- let signatures = &[fn_signature];
- let fn_ptrs = &mut [ptr::null()];
- let mut dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
-
- let result = dispatch_table.ptrs_mut();
- assert_eq!(result.len(), fn_ptrs.len());
- for (lhs, rhs) in result.iter().zip(fn_ptrs.iter()) {
- assert_eq!(lhs, rhs);
- }
- }
-
- #[test]
- fn test_dispatch_table_signatures() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- let signatures = &[fn_signature];
- let fn_ptrs = &mut [ptr::null()];
- let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
-
- let result = dispatch_table.signatures();
- assert_eq!(result.len(), signatures.len());
- for (lhs, rhs) in result.iter().zip(signatures.iter()) {
- assert_eq!(lhs.name(), rhs.name());
- assert_eq!(lhs.arg_types(), rhs.arg_types());
- assert_eq!(lhs.return_type(), rhs.return_type());
- assert_eq!(lhs.privacy(), rhs.privacy());
- }
- }
-
- #[test]
- fn test_dispatch_table_get_ptr_unchecked() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- let signatures = &[fn_signature];
- let fn_ptrs = &mut [ptr::null()];
-
- let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
- assert_eq!(unsafe { dispatch_table.get_ptr_unchecked(0) }, fn_ptrs[0]);
- }
-
- #[test]
- fn test_dispatch_table_get_ptr_none() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- let signatures = &[fn_signature];
- let fn_ptrs = &mut [ptr::null()];
-
- let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
- assert_eq!(dispatch_table.get_ptr(1), None);
- }
-
- #[test]
- fn test_dispatch_table_get_ptr_some() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- let signatures = &[fn_signature];
- let fn_ptrs = &mut [ptr::null()];
-
- let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
- assert_eq!(dispatch_table.get_ptr(0), Some(fn_ptrs[0]));
- }
-
- #[test]
- fn test_dispatch_table_get_ptr_unchecked_mut() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- let signatures = &[fn_signature];
- let fn_ptrs = &mut [ptr::null()];
-
- let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
- assert_eq!(
- unsafe { dispatch_table.get_ptr_unchecked_mut(0) },
- &mut fn_ptrs[0]
- );
- }
-
- #[test]
- fn test_dispatch_table_get_ptr_mut_none() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- let signatures = &[fn_signature];
- let fn_ptrs = &mut [ptr::null()];
-
- let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
- assert_eq!(dispatch_table.get_ptr_mut(1), None);
- }
-
- #[test]
- fn test_dispatch_table_get_ptr_mut_some() {
- let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
- let type_info = fake_type_info(&type_name);
-
- let return_type = Some(&type_info);
- let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
- let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
-
- let signatures = &[fn_signature];
- let fn_ptrs = &mut [ptr::null()];
-
- let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
- assert_eq!(dispatch_table.get_ptr_mut(0), Some(&mut fn_ptrs[0]));
- }
-
- fn fake_assembly_info(
- symbols: ModuleInfo,
- dispatch_table: DispatchTable,
- dependencies: &[*const c_char],
- ) -> AssemblyInfo {
- AssemblyInfo {
- symbols,
- dispatch_table,
- dependencies: dependencies.as_ptr(),
- num_dependencies: dependencies.len() as u32,
- }
- }
-
- const FAKE_DEPENDENCY: &'static str = "path/to/dependency.dylib";
-
- #[test]
- fn test_assembly_info_dependencies() {
- let module_path = CString::new(FAKE_MODULE_PATH).expect("Invalid fake module path.");
- let module = fake_module_info(&module_path, &[]);
-
- let dispatch_table = fake_dispatch_table(&[], &mut []);
-
- let dependency = CString::new(FAKE_DEPENDENCY).expect("Invalid fake dependency.");
- let dependencies = &[dependency.as_ptr()];
- let assembly = fake_assembly_info(module, dispatch_table, dependencies);
-
- assert_eq!(assembly.dependencies().count(), dependencies.len());
- for (lhs, rhs) in assembly.dependencies().zip([FAKE_DEPENDENCY].iter()) {
- assert_eq!(lhs, *rhs)
- }
- }
+#[doc = "
"]
+#[repr(C)]
+#[derive(Clone)]
+pub struct FunctionInfo {
+ pub signature: FunctionSignature,
+ pub fn_ptr: *const ::std::os::raw::c_void,
+}
+#[test]
+fn bindgen_test_layout_FunctionInfo() {
+ assert_eq!(
+ ::std::mem::size_of::
(),
+ 40usize,
+ concat!("Size of: ", stringify!(FunctionInfo))
+ );
+ assert_eq!(
+ ::std::mem::align_of::(),
+ 8usize,
+ concat!("Alignment of ", stringify!(FunctionInfo))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).signature as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(FunctionInfo),
+ "::",
+ stringify!(signature)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).fn_ptr as *const _ as usize },
+ 32usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(FunctionInfo),
+ "::",
+ stringify!(fn_ptr)
+ )
+ );
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct ModuleInfo {
+ pub path: *const ::std::os::raw::c_char,
+ pub functions: *const FunctionInfo,
+ pub num_functions: u32,
+}
+#[test]
+fn bindgen_test_layout_ModuleInfo() {
+ assert_eq!(
+ ::std::mem::size_of::(),
+ 24usize,
+ concat!("Size of: ", stringify!(ModuleInfo))
+ );
+ assert_eq!(
+ ::std::mem::align_of::(),
+ 8usize,
+ concat!("Alignment of ", stringify!(ModuleInfo))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).path as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(ModuleInfo),
+ "::",
+ stringify!(path)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).functions as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(ModuleInfo),
+ "::",
+ stringify!(functions)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).num_functions as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(ModuleInfo),
+ "::",
+ stringify!(num_functions)
+ )
+ );
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct DispatchTable {
+ pub signatures: *const FunctionSignature,
+ pub fn_ptrs: *mut *const ::std::os::raw::c_void,
+ pub num_entries: u32,
+}
+#[test]
+fn bindgen_test_layout_DispatchTable() {
+ assert_eq!(
+ ::std::mem::size_of::(),
+ 24usize,
+ concat!("Size of: ", stringify!(DispatchTable))
+ );
+ assert_eq!(
+ ::std::mem::align_of::(),
+ 8usize,
+ concat!("Alignment of ", stringify!(DispatchTable))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).signatures as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(DispatchTable),
+ "::",
+ stringify!(signatures)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).fn_ptrs as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(DispatchTable),
+ "::",
+ stringify!(fn_ptrs)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).num_entries as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(DispatchTable),
+ "::",
+ stringify!(num_entries)
+ )
+ );
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct AssemblyInfo {
+ pub symbols: ModuleInfo,
+ pub dispatch_table: DispatchTable,
+ pub dependencies: *const *const ::std::os::raw::c_char,
+ pub num_dependencies: u32,
+}
+#[test]
+fn bindgen_test_layout_AssemblyInfo() {
+ assert_eq!(
+ ::std::mem::size_of::(),
+ 64usize,
+ concat!("Size of: ", stringify!(AssemblyInfo))
+ );
+ assert_eq!(
+ ::std::mem::align_of::(),
+ 8usize,
+ concat!("Alignment of ", stringify!(AssemblyInfo))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).symbols as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(AssemblyInfo),
+ "::",
+ stringify!(symbols)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).dispatch_table as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(AssemblyInfo),
+ "::",
+ stringify!(dispatch_table)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).dependencies as *const _ as usize },
+ 48usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(AssemblyInfo),
+ "::",
+ stringify!(dependencies)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::())).num_dependencies as *const _ as usize },
+ 56usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(AssemblyInfo),
+ "::",
+ stringify!(num_dependencies)
+ )
+ );
}
diff --git a/crates/mun_abi/src/autogen_impl.rs b/crates/mun_abi/src/autogen_impl.rs
new file mode 100644
index 000000000..7d35de78d
--- /dev/null
+++ b/crates/mun_abi/src/autogen_impl.rs
@@ -0,0 +1,575 @@
+use crate::prelude::*;
+
+use std::ffi::{c_void, CStr};
+use std::marker::{Send, Sync};
+use std::slice;
+
+impl TypeInfo {
+ /// Returns the type's name.
+ pub fn name(&self) -> &str {
+ unsafe { CStr::from_ptr(self.name) }
+ .to_str()
+ .expect("Type name contains invalid UTF8")
+ }
+}
+
+impl PartialEq for TypeInfo {
+ fn eq(&self, other: &Self) -> bool {
+ self.guid == other.guid
+ }
+}
+
+unsafe impl Send for TypeInfo {}
+unsafe impl Sync for TypeInfo {}
+
+impl FunctionSignature {
+ /// Returns the function's name.
+ pub fn name(&self) -> &str {
+ unsafe { CStr::from_ptr(self.name) }
+ .to_str()
+ .expect("Function name contains invalid UTF8")
+ }
+
+ /// Returns the function's privacy level.
+ pub fn privacy(&self) -> Privacy {
+ self.privacy
+ }
+
+ /// Returns the function's arguments' types.
+ pub fn arg_types(&self) -> &[TypeInfo] {
+ if self.num_arg_types == 0 {
+ &[]
+ } else {
+ unsafe { slice::from_raw_parts(self.arg_types, self.num_arg_types as usize) }
+ }
+ }
+
+ /// Returns the function's return type
+ pub fn return_type(&self) -> Option<&TypeInfo> {
+ unsafe { self.return_type.as_ref() }
+ }
+}
+
+unsafe impl Send for FunctionSignature {}
+unsafe impl Sync for FunctionSignature {}
+
+unsafe impl Send for FunctionInfo {}
+unsafe impl Sync for FunctionInfo {}
+
+impl ModuleInfo {
+ /// Returns the module's full path.
+ pub fn path(&self) -> &str {
+ unsafe { CStr::from_ptr(self.path) }
+ .to_str()
+ .expect("Module path contains invalid UTF8")
+ }
+
+ // /// Finds the type's fields that match `filter`.
+ // pub fn find_fields(&self, filter: fn(&&FieldInfo) -> bool) -> impl Iterator- {
+ // self.fields.iter().map(|f| *f).filter(filter)
+ // }
+
+ // /// Retrieves the type's field with the specified `name`, if it exists.
+ // pub fn get_field(&self, name: &str) -> Option<&FieldInfo> {
+ // self.fields.iter().find(|f| f.name == name).map(|f| *f)
+ // }
+
+ // /// Retrieves the type's fields.
+ // pub fn get_fields(&self) -> impl Iterator
- {
+ // self.fields.iter().map(|f| *f)
+ // }
+
+ /// Returns the module's functions.
+ pub fn functions(&self) -> &[FunctionInfo] {
+ if self.num_functions == 0 {
+ &[]
+ } else {
+ unsafe { slice::from_raw_parts(self.functions, self.num_functions as usize) }
+ }
+ }
+}
+
+unsafe impl Send for ModuleInfo {}
+unsafe impl Sync for ModuleInfo {}
+
+impl DispatchTable {
+ /// Returns an iterator over pairs of mutable function pointers and signatures.
+ pub fn iter_mut(&mut self) -> impl Iterator
- {
+ if self.num_entries == 0 {
+ (&mut []).iter_mut().zip((&[]).iter())
+ } else {
+ let ptrs =
+ unsafe { slice::from_raw_parts_mut(self.fn_ptrs, self.num_entries as usize) };
+ let signatures =
+ unsafe { slice::from_raw_parts(self.signatures, self.num_entries as usize) };
+
+ ptrs.iter_mut().zip(signatures.iter())
+ }
+ }
+
+ /// Returns mutable functions pointers.
+ pub fn ptrs_mut(&mut self) -> &mut [*const c_void] {
+ if self.num_entries == 0 {
+ &mut []
+ } else {
+ unsafe { slice::from_raw_parts_mut(self.fn_ptrs, self.num_entries as usize) }
+ }
+ }
+
+ /// Returns function signatures.
+ pub fn signatures(&self) -> &[FunctionSignature] {
+ if self.num_entries == 0 {
+ &[]
+ } else {
+ unsafe { slice::from_raw_parts(self.signatures, self.num_entries as usize) }
+ }
+ }
+
+ /// Returns a function pointer, without doing bounds checking.
+ ///
+ /// This is generally not recommended, use with caution! Calling this method with an
+ /// out-of-bounds index is _undefined behavior_ even if the resulting reference is not used.
+ /// For a safe alternative see [get_ptr](#method.get_ptr).
+ pub unsafe fn get_ptr_unchecked(&self, idx: u32) -> *const c_void {
+ *self.fn_ptrs.offset(idx as isize)
+ }
+
+ /// Returns a function pointer at the given index, or `None` if out of bounds.
+ pub fn get_ptr(&self, idx: u32) -> Option<*const c_void> {
+ if idx < self.num_entries {
+ Some(unsafe { self.get_ptr_unchecked(idx) })
+ } else {
+ None
+ }
+ }
+
+ /// Returns a mutable reference to a function pointer, without doing bounds checking.
+ ///
+ /// This is generally not recommended, use with caution! Calling this method with an
+ /// out-of-bounds index is _undefined behavior_ even if the resulting reference is not used.
+ /// For a safe alternative see [get_ptr_mut](#method.get_ptr_mut).
+ pub unsafe fn get_ptr_unchecked_mut(&self, idx: u32) -> &mut *const c_void {
+ &mut *self.fn_ptrs.offset(idx as isize)
+ }
+
+ /// Returns a mutable reference to a function pointer at the given index, or `None` if out of
+ /// bounds.
+ pub fn get_ptr_mut(&self, idx: u32) -> Option<&mut *const c_void> {
+ if idx < self.num_entries {
+ Some(unsafe { self.get_ptr_unchecked_mut(idx) })
+ } else {
+ None
+ }
+ }
+}
+
+impl AssemblyInfo {
+ /// Returns an iterator over the assembly's dependencies.
+ pub fn dependencies(&self) -> impl Iterator
- {
+ let dependencies = if self.num_dependencies == 0 {
+ &[]
+ } else {
+ unsafe { slice::from_raw_parts(self.dependencies, self.num_dependencies as usize) }
+ };
+
+ dependencies.iter().map(|d| {
+ unsafe { CStr::from_ptr(*d) }
+ .to_str()
+ .expect("dependency path contains invalid UTF8")
+ })
+ }
+}
+
+unsafe impl Send for AssemblyInfo {}
+unsafe impl Sync for AssemblyInfo {}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::ffi::CString;
+ use std::os::raw::c_char;
+ use std::ptr;
+
+ fn fake_type_info(name: &CStr) -> TypeInfo {
+ TypeInfo {
+ guid: FAKE_TYPE_GUID,
+ name: name.as_ptr(),
+ }
+ }
+
+ const FAKE_TYPE_GUID: Guid = Guid {
+ b: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
+ };
+
+ const FAKE_TYPE_NAME: &'static str = "type-name";
+
+ #[test]
+ fn test_type_info_name() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ assert_eq!(type_info.name(), FAKE_TYPE_NAME);
+ }
+
+ #[test]
+ fn test_type_info_eq() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ assert_eq!(type_info, type_info);
+ }
+
+ fn fake_fn_signature(
+ name: &CStr,
+ arg_types: &[TypeInfo],
+ return_type: Option<&TypeInfo>,
+ privacy: Privacy,
+ ) -> FunctionSignature {
+ FunctionSignature {
+ name: name.as_ptr(),
+ arg_types: arg_types.as_ptr(),
+ return_type: return_type.map_or(ptr::null(), |t| t as *const TypeInfo),
+ num_arg_types: arg_types.len() as u16,
+ privacy,
+ }
+ }
+
+ const FAKE_FN_NAME: &'static str = "fn-name";
+
+ #[test]
+ fn test_fn_signature_name() {
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], None, Privacy::Public);
+
+ assert_eq!(fn_signature.name(), FAKE_FN_NAME);
+ }
+
+ #[test]
+ fn test_fn_signature_privacy() {
+ let privacy = Privacy::Private;
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], None, privacy);
+
+ assert_eq!(fn_signature.privacy(), privacy);
+ }
+
+ #[test]
+ fn test_fn_signature_arg_types_none() {
+ let arg_types = &[];
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, arg_types, None, Privacy::Public);
+
+ assert_eq!(fn_signature.arg_types(), arg_types);
+ }
+
+ #[test]
+ fn test_fn_signature_arg_types_some() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let arg_types = &[type_info];
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, arg_types, None, Privacy::Public);
+
+ assert_eq!(fn_signature.arg_types(), arg_types);
+ }
+
+ #[test]
+ fn test_fn_signature_return_type_none() {
+ let return_type = None;
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ assert_eq!(fn_signature.return_type(), return_type);
+ }
+
+ #[test]
+ fn test_fn_signature_return_type_some() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ assert_eq!(fn_signature.return_type(), return_type);
+ }
+
+ fn fake_module_info(path: &CStr, functions: &[FunctionInfo]) -> ModuleInfo {
+ ModuleInfo {
+ path: path.as_ptr(),
+ functions: functions.as_ptr(),
+ num_functions: functions.len() as u32,
+ }
+ }
+
+ const FAKE_MODULE_PATH: &'static str = "path::to::module";
+
+ #[test]
+ fn test_module_info_path() {
+ let module_path = CString::new(FAKE_MODULE_PATH).expect("Invalid fake module path.");
+ let module = fake_module_info(&module_path, &[]);
+
+ assert_eq!(module.path(), FAKE_MODULE_PATH);
+ }
+
+ #[test]
+ fn test_module_info_functions_none() {
+ let functions = &[];
+ let module_path = CString::new(FAKE_MODULE_PATH).expect("Invalid fake module path.");
+ let module = fake_module_info(&module_path, functions);
+
+ assert_eq!(module.functions().len(), functions.len());
+ }
+
+ #[test]
+ fn test_module_info_functions_some() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ let fn_info = FunctionInfo {
+ signature: fn_signature,
+ fn_ptr: ptr::null(),
+ };
+
+ let functions = &[fn_info];
+ let module_path = CString::new(FAKE_MODULE_PATH).expect("Invalid fake module path.");
+ let module = fake_module_info(&module_path, functions);
+
+ let result = module.functions();
+ assert_eq!(result.len(), functions.len());
+ for (lhs, rhs) in result.iter().zip(functions.iter()) {
+ assert_eq!(lhs.fn_ptr, rhs.fn_ptr);
+ assert_eq!(lhs.signature.name(), rhs.signature.name());
+ assert_eq!(lhs.signature.arg_types(), rhs.signature.arg_types());
+ assert_eq!(lhs.signature.return_type(), rhs.signature.return_type());
+ assert_eq!(lhs.signature.privacy(), rhs.signature.privacy());
+ }
+ }
+
+ fn fake_dispatch_table(
+ fn_signatures: &[FunctionSignature],
+ fn_ptrs: &mut [*const c_void],
+ ) -> DispatchTable {
+ assert!(fn_signatures.len() == fn_ptrs.len());
+
+ DispatchTable {
+ signatures: fn_signatures.as_ptr(),
+ fn_ptrs: fn_ptrs.as_mut_ptr(),
+ num_entries: fn_signatures.len() as u32,
+ }
+ }
+
+ #[test]
+ fn test_dispatch_table_iter_mut_none() {
+ let signatures = &[];
+ let fn_ptrs = &mut [];
+ let mut dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
+
+ let iter = fn_ptrs.iter_mut().zip(signatures.iter());
+ assert_eq!(dispatch_table.iter_mut().count(), iter.count());
+ }
+
+ #[test]
+ fn test_dispatch_table_iter_mut_some() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ let signatures = &[fn_signature];
+ let fn_ptrs = &mut [ptr::null()];
+ let mut dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
+
+ let iter = fn_ptrs.iter_mut().zip(signatures.iter());
+ assert_eq!(dispatch_table.iter_mut().count(), iter.len());
+
+ for (lhs, rhs) in dispatch_table.iter_mut().zip(iter) {
+ assert_eq!(lhs.0, rhs.0);
+ assert_eq!(lhs.1.name(), rhs.1.name());
+ assert_eq!(lhs.1.arg_types(), rhs.1.arg_types());
+ assert_eq!(lhs.1.return_type(), rhs.1.return_type());
+ assert_eq!(lhs.1.privacy(), rhs.1.privacy());
+ }
+ }
+
+ #[test]
+ fn test_dispatch_table_ptrs_mut() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ let signatures = &[fn_signature];
+ let fn_ptrs = &mut [ptr::null()];
+ let mut dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
+
+ let result = dispatch_table.ptrs_mut();
+ assert_eq!(result.len(), fn_ptrs.len());
+ for (lhs, rhs) in result.iter().zip(fn_ptrs.iter()) {
+ assert_eq!(lhs, rhs);
+ }
+ }
+
+ #[test]
+ fn test_dispatch_table_signatures() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ let signatures = &[fn_signature];
+ let fn_ptrs = &mut [ptr::null()];
+ let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
+
+ let result = dispatch_table.signatures();
+ assert_eq!(result.len(), signatures.len());
+ for (lhs, rhs) in result.iter().zip(signatures.iter()) {
+ assert_eq!(lhs.name(), rhs.name());
+ assert_eq!(lhs.arg_types(), rhs.arg_types());
+ assert_eq!(lhs.return_type(), rhs.return_type());
+ assert_eq!(lhs.privacy(), rhs.privacy());
+ }
+ }
+
+ #[test]
+ fn test_dispatch_table_get_ptr_unchecked() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ let signatures = &[fn_signature];
+ let fn_ptrs = &mut [ptr::null()];
+
+ let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
+ assert_eq!(unsafe { dispatch_table.get_ptr_unchecked(0) }, fn_ptrs[0]);
+ }
+
+ #[test]
+ fn test_dispatch_table_get_ptr_none() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ let signatures = &[fn_signature];
+ let fn_ptrs = &mut [ptr::null()];
+
+ let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
+ assert_eq!(dispatch_table.get_ptr(1), None);
+ }
+
+ #[test]
+ fn test_dispatch_table_get_ptr_some() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ let signatures = &[fn_signature];
+ let fn_ptrs = &mut [ptr::null()];
+
+ let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
+ assert_eq!(dispatch_table.get_ptr(0), Some(fn_ptrs[0]));
+ }
+
+ #[test]
+ fn test_dispatch_table_get_ptr_unchecked_mut() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ let signatures = &[fn_signature];
+ let fn_ptrs = &mut [ptr::null()];
+
+ let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
+ assert_eq!(
+ unsafe { dispatch_table.get_ptr_unchecked_mut(0) },
+ &mut fn_ptrs[0]
+ );
+ }
+
+ #[test]
+ fn test_dispatch_table_get_ptr_mut_none() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ let signatures = &[fn_signature];
+ let fn_ptrs = &mut [ptr::null()];
+
+ let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
+ assert_eq!(dispatch_table.get_ptr_mut(1), None);
+ }
+
+ #[test]
+ fn test_dispatch_table_get_ptr_mut_some() {
+ let type_name = CString::new(FAKE_TYPE_NAME).expect("Invalid fake type name.");
+ let type_info = fake_type_info(&type_name);
+
+ let return_type = Some(&type_info);
+ let fn_name = CString::new(FAKE_FN_NAME).expect("Invalid fake fn name.");
+ let fn_signature = fake_fn_signature(&fn_name, &[], return_type, Privacy::Public);
+
+ let signatures = &[fn_signature];
+ let fn_ptrs = &mut [ptr::null()];
+
+ let dispatch_table = fake_dispatch_table(signatures, fn_ptrs);
+ assert_eq!(dispatch_table.get_ptr_mut(0), Some(&mut fn_ptrs[0]));
+ }
+
+ fn fake_assembly_info(
+ symbols: ModuleInfo,
+ dispatch_table: DispatchTable,
+ dependencies: &[*const c_char],
+ ) -> AssemblyInfo {
+ AssemblyInfo {
+ symbols,
+ dispatch_table,
+ dependencies: dependencies.as_ptr(),
+ num_dependencies: dependencies.len() as u32,
+ }
+ }
+
+ const FAKE_DEPENDENCY: &'static str = "path/to/dependency.dylib";
+
+ #[test]
+ fn test_assembly_info_dependencies() {
+ let module_path = CString::new(FAKE_MODULE_PATH).expect("Invalid fake module path.");
+ let module = fake_module_info(&module_path, &[]);
+
+ let dispatch_table = fake_dispatch_table(&[], &mut []);
+
+ let dependency = CString::new(FAKE_DEPENDENCY).expect("Invalid fake dependency.");
+ let dependencies = &[dependency.as_ptr()];
+ let assembly = fake_assembly_info(module, dispatch_table, dependencies);
+
+ assert_eq!(assembly.dependencies().count(), dependencies.len());
+ for (lhs, rhs) in assembly.dependencies().zip([FAKE_DEPENDENCY].iter()) {
+ assert_eq!(lhs, *rhs)
+ }
+ }
+}
diff --git a/crates/mun_abi/src/lib.rs b/crates/mun_abi/src/lib.rs
index 998fe9e5c..3a4f37c27 100644
--- a/crates/mun_abi/src/lib.rs
+++ b/crates/mun_abi/src/lib.rs
@@ -1,4 +1,7 @@
+// Bindings are automatically generated from C on `cargo build`
mod autogen;
+
+mod autogen_impl;
mod macros;
mod reflection;
diff --git a/crates/mun_runtime/src/macros.rs b/crates/mun_runtime/src/macros.rs
index 0cd6f8805..5cc79a88f 100644
--- a/crates/mun_runtime/src/macros.rs
+++ b/crates/mun_runtime/src/macros.rs
@@ -56,7 +56,7 @@ macro_rules! invoke_fn_impl {
while !err.runtime.update() {
// Wait until there has been an update that might fix the error
}
- err.runtime.$FnName(err.function_name, $(err.$Arg,)*)
+ $crate::MunRuntime::$FnName(err.runtime, err.function_name, $(err.$Arg,)*)
}
}
}
@@ -78,18 +78,18 @@ macro_rules! invoke_fn_impl {
/// If an error occurs when invoking the method, an error message is logged. The
/// runtime continues looping until the cause of the error has been resolved.
pub fn $FnName<'r, 's, $($T: Reflection,)* Output: Reflection>(
- &'r mut self,
+ runtime: &'r mut MunRuntime,
function_name: &'s str,
$($Arg: $T,)*
) -> core::result::Result