1use std::boxed::Box as Ptr;
4
5pub trait VTable<T> {
16 fn build_vtable() -> Self;
17}
18
19impl<T: Copy> VTable<T> for () {
20 #[inline]
21 fn build_vtable() -> Self {}
22}
23
24#[cfg(feature = "traits")]
25impl<T: crate::traits::DropBytes, V: VTable<T>> VTable<T> for (crate::traits::DropFn, V) {
26 #[inline]
27 fn build_vtable() -> Self {
28 (T::drop_bytes, V::build_vtable())
29 }
30}
31
32#[derive(Clone, Debug, PartialEq)]
37pub enum VTableRef<'a, V>
38where
39 V: ?Sized,
40{
41 Ref(&'a V),
42 Box(Box<V>),
43 }
45
46impl<'a, V: Clone + ?Sized> VTableRef<'a, V> {
47 #[inline]
48 pub fn take(self) -> V {
49 match self {
50 VTableRef::Ref(v) => v.clone(),
51 VTableRef::Box(v) => *v,
52 }
54 }
55
56 #[inline]
57 pub fn into_owned(self) -> Ptr<V> {
58 match self {
59 VTableRef::Ref(v) => Ptr::new(v.clone()),
60 VTableRef::Box(v) => v,
61 }
63 }
64}
65
66impl<'a, V: ?Sized> std::ops::Deref for VTableRef<'a, V> {
67 type Target = V;
68 #[inline]
69 fn deref(&self) -> &Self::Target {
70 self.as_ref()
71 }
72}
73
74impl<'a, V: ?Sized> From<&'a V> for VTableRef<'a, V> {
75 #[inline]
76 fn from(v: &'a V) -> VTableRef<'a, V> {
77 VTableRef::Ref(v)
78 }
79}
80
81impl<'a, V: ?Sized> From<Box<V>> for VTableRef<'a, V> {
82 #[inline]
83 fn from(v: Box<V>) -> VTableRef<'a, V> {
84 VTableRef::Box(v)
85 }
86}
87
88impl<'a, V: ?Sized> AsRef<V> for VTableRef<'a, V> {
96 #[inline]
97 fn as_ref(&self) -> &V {
98 match self {
99 VTableRef::Ref(v) => v,
100 VTableRef::Box(v) => &*v,
101 }
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn box_vtable() {
112 let v = Box::new(());
113 let from_box = VTableRef::from(v.clone());
114 let box_vtable = VTableRef::Box(v);
115 assert_eq!(&from_box, &box_vtable);
116
117 assert_eq!(from_box.into_owned(), Box::new(()));
118 assert_eq!(box_vtable.take(), ());
119 }
120}