1#![no_std]
2
3extern crate self as cppvtbl;
4
5use core::{
6 marker::PhantomPinned,
7 mem,
8 ops::{Deref, DerefMut},
9 pin::Pin,
10};
11
12#[cfg(feature = "macros")]
13pub use cppvtbl_macros::{impl_vtables, vtable};
14
15#[repr(C)]
16pub struct WithVtables<T: HasVtables> {
17 vtables: T::Tables,
18 value: T,
19}
20impl<T: HasVtables> WithVtables<T> {
21 pub fn new(value: T) -> Self {
22 Self {
23 vtables: T::TABLES,
24 value,
25 }
26 }
27 pub fn vtables(&self) -> &T::Tables {
28 &self.vtables
29 }
30 pub fn vtables_mut(&mut self) -> *mut T::Tables {
32 &mut self.vtables
33 }
34}
35impl<T: HasVtables> From<T> for WithVtables<T> {
36 fn from(value: T) -> Self {
37 Self::new(value)
38 }
39}
40impl<T: HasVtables> Deref for WithVtables<T> {
41 type Target = T;
42
43 fn deref(&self) -> &Self::Target {
44 &self.value
45 }
46}
47impl<T: HasVtables> DerefMut for WithVtables<T> {
48 fn deref_mut(&mut self) -> &mut Self::Target {
49 &mut self.value
50 }
51}
52
53pub unsafe trait HasVtables {
54 type Tables;
55 const TABLES: Self::Tables;
56}
57
58#[repr(transparent)]
59pub struct VtableRef<V: 'static>(&'static V, PhantomPinned);
60impl<V: 'static> VtableRef<V> {
61 pub const unsafe fn new(vtable: &'static V) -> Self {
64 Self(vtable, PhantomPinned)
65 }
66 pub fn table(&self) -> &'static V {
67 self.0
68 }
69 pub fn into_raw(v: &Self) -> *const VtableRef<V> {
70 v as *const _
71 }
72 pub fn into_raw_mut(v: Pin<&mut Self>) -> *mut VtableRef<V> {
73 unsafe { Pin::get_unchecked_mut(v) as *mut _ }
76 }
77 pub unsafe fn from_raw<'r>(raw: *const VtableRef<V>) -> &'r Self {
79 mem::transmute(raw as *const _ as *const Self)
80 }
81 pub unsafe fn from_raw_mut<'r>(raw: *mut VtableRef<V>) -> Pin<&'r mut Self> {
83 mem::transmute(raw as *mut _ as *mut Self)
84 }
85}
86
87pub trait HasVtable<V>: Sized + HasVtables {
88 fn get(from: &WithVtables<Self>) -> &VtableRef<V>;
89 fn get_mut(from: &mut WithVtables<Self>) -> Pin<&mut VtableRef<V>>;
91}