Skip to main content

vtable_rs/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3
4use core::ops::{Deref, DerefMut};
5
6#[doc(inline)]
7pub use vtable_rs_proc_macros::vtable;
8
9/// Provides compile-time virtual method table references for the concrete type `T`.
10///
11/// This trait is implemented on the vtable trait object, e.g. `dyn MyVtable`.
12pub trait VmtInstance<T: 'static>: 'static + VmtLayout {
13    const VTABLE: &'static Self::Layout<T>;
14}
15
16/// Provides concrete virtual method table layouts for a vtable trait.
17///
18/// # Safety
19///
20/// Implementing this trait manually does not currently require abiding by any safety invariants.
21/// However, this may change in future versions.
22pub unsafe trait VmtLayout: 'static {
23    type Layout<T: 'static>: 'static + Copy + Send + Sync;
24}
25
26#[repr(C)]
27pub struct VPtr<V: VmtLayout + ?Sized, T: 'static>(&'static <V as VmtLayout>::Layout<T>);
28
29impl<V: VmtLayout + ?Sized, T: 'static> Deref for VPtr<V, T> {
30    type Target = &'static <V as VmtLayout>::Layout<T>;
31    fn deref(&self) -> &Self::Target {
32        &self.0
33    }
34}
35
36impl<V: VmtLayout + ?Sized, T: 'static> DerefMut for VPtr<V, T> {
37    fn deref_mut(&mut self) -> &mut Self::Target {
38        &mut self.0
39    }
40}
41
42impl<V: VmtLayout + ?Sized, T: 'static> core::fmt::Debug for VPtr<V, T> {
43    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
44        f.debug_struct(core::any::type_name::<Self>())
45            .field(
46                "vtable",
47                &format_args!("{:X}", core::ptr::addr_of!(*self.0) as usize),
48            )
49            .finish()
50    }
51}
52
53impl<V: VmtLayout + ?Sized, T: 'static> Clone for VPtr<V, T> {
54    fn clone(&self) -> Self {
55        *self
56    }
57}
58
59impl<V: VmtLayout + ?Sized, T: 'static> Copy for VPtr<V, T> {}
60
61impl<T, V: VmtInstance<T> + ?Sized> VPtr<V, T> {
62    /// Construct a [`VPtr`] initialized with a pointer to `T`'s vtable for `V`.
63    ///
64    /// This is the same as the [`Default::default`] implementation, but `const`.
65    pub const fn new() -> Self {
66        VPtr(vmt_instance::<V, T>())
67    }
68}
69
70impl<T, V: VmtInstance<T> + ?Sized> Default for VPtr<V, T> {
71    fn default() -> Self {
72        VPtr(vmt_instance::<V, T>())
73    }
74}
75
76pub const fn vmt_instance<V: VmtInstance<T> + ?Sized, T>() -> &'static V::Layout<T> {
77    V::VTABLE
78}