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
9pub trait VmtInstance<T: 'static>: 'static + VmtLayout {
13 const VTABLE: &'static Self::Layout<T>;
14}
15
16pub 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 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}