1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use std::{ffi::CStr, os::raw::c_char, slice, str};
use crate::{DispatchTable, ModuleInfo, TypeLut};
#[repr(C)]
pub struct AssemblyInfo<'a> {
pub symbols: ModuleInfo<'a>,
pub dispatch_table: DispatchTable<'a>,
pub type_lut: TypeLut<'a>,
pub(crate) dependencies: *const *const c_char,
pub num_dependencies: u32,
}
impl<'a> AssemblyInfo<'a> {
pub fn dependencies(&self) -> impl Iterator<Item = &str> {
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 { str::from_utf8_unchecked(CStr::from_ptr(*d).to_bytes()) })
}
}
unsafe impl<'a> Send for AssemblyInfo<'a> {}
unsafe impl<'a> Sync for AssemblyInfo<'a> {}
#[cfg(feature = "serde")]
impl<'a> serde::Serialize for AssemblyInfo<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use itertools::Itertools;
use serde::ser::SerializeStruct;
let mut s = serializer.serialize_struct("AssemblyInfo", 4)?;
s.serialize_field("symbols", &self.symbols)?;
s.serialize_field("dispatch_table", &self.dispatch_table)?;
s.serialize_field("type_lut", &self.type_lut)?;
s.serialize_field("dependencies", &self.dependencies().collect_vec())?;
s.end()
}
}
#[cfg(test)]
mod tests {
use std::ffi::CString;
use crate::test_utils::{
fake_assembly_info, fake_dispatch_table, fake_module_info, fake_type_lut, FAKE_DEPENDENCY,
FAKE_MODULE_PATH,
};
#[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 type_lut = fake_type_lut(&[], &mut [], &[]);
let dependency = CString::new(FAKE_DEPENDENCY).expect("Invalid fake dependency.");
let dependencies = &[dependency.as_ptr()];
let assembly = fake_assembly_info(module, dispatch_table, type_lut, dependencies);
assert_eq!(assembly.dependencies().count(), dependencies.len());
for (lhs, rhs) in assembly.dependencies().zip([FAKE_DEPENDENCY].iter()) {
assert_eq!(lhs, *rhs)
}
}
}