rune/runtime/
vm_diagnostics.rs

1use core::ptr::NonNull;
2
3use crate::hash::Hash;
4use crate::runtime::VmError;
5use crate::Diagnostics;
6
7/// A trait for runtime diagnostics in the virtual machine.
8pub trait VmDiagnostics {
9    /// Mark that a function has been used.
10    fn function_used(&mut self, hash: Hash, at: usize) -> Result<(), VmError>;
11
12    /// Returns the vtable for this diagnostics object.
13    #[doc(hidden)]
14    fn vtable(&self) -> &'static VmDiagnosticsObjVtable;
15}
16
17impl VmDiagnostics for Diagnostics {
18    #[inline]
19    fn function_used(&mut self, hash: Hash, at: usize) -> Result<(), VmError> {
20        self.runtime_used_deprecated(at, hash)?;
21        Ok(())
22    }
23
24    #[inline]
25    fn vtable(&self) -> &'static VmDiagnosticsObjVtable {
26        fn function_used_impl<T>(ptr: NonNull<()>, hash: Hash, at: usize) -> Result<(), VmError>
27        where
28            T: VmDiagnostics,
29        {
30            unsafe { VmDiagnostics::function_used(ptr.cast::<T>().as_mut(), hash, at) }
31        }
32
33        &VmDiagnosticsObjVtable {
34            function_used: function_used_impl::<Self>,
35        }
36    }
37}
38
39#[derive(Debug)]
40pub struct VmDiagnosticsObjVtable {
41    function_used: unsafe fn(NonNull<()>, hash: Hash, at: usize) -> Result<(), VmError>,
42}
43
44#[repr(C)]
45#[derive(Debug, Clone, Copy)]
46pub(crate) struct VmDiagnosticsObj {
47    ptr: NonNull<()>,
48    vtable: &'static VmDiagnosticsObjVtable,
49}
50
51impl VmDiagnosticsObj {
52    #[inline]
53    pub(crate) fn new(trait_obj: &mut dyn VmDiagnostics) -> Self {
54        let vtable = trait_obj.vtable();
55
56        Self {
57            ptr: unsafe { NonNull::new_unchecked(trait_obj as *mut _ as *mut ()) },
58            vtable,
59        }
60    }
61
62    #[inline]
63    pub(crate) fn function_used(&mut self, hash: Hash, at: usize) -> Result<(), VmError> {
64        unsafe { (self.vtable.function_used)(self.ptr, hash, at) }
65    }
66}