abi_stable/abi_stability/
const_generics.rs1use crate::{
4 abi_stability::{
5 check_layout_compatibility,
6 extra_checks::{ExtraChecksError, TypeCheckerMut},
7 },
8 erased_types::{
9 c_functions::{adapt_std_fmt, debug_impl, partial_eq_impl},
10 FormattingMode,
11 },
12 marker_type::ErasedObject,
13 prefix_type::WithMetadata,
14 sabi_types::RRef,
15 std_types::{RErr, ROk, RResult, RString},
16 type_layout::TypeLayout,
17 StableAbi,
18};
19
20use std::{
21 cmp::{Eq, PartialEq},
22 fmt::{self, Debug},
23};
24
25#[repr(C)]
29#[derive(Copy, Clone, StableAbi)]
30pub struct ConstGeneric {
31 ptr: RRef<'static, ErasedObject>,
32 vtable: ConstGenericVTable_Ref,
33}
34
35unsafe impl Send for ConstGeneric {}
36unsafe impl Sync for ConstGeneric {}
37
38impl ConstGeneric {
39 pub const fn new<T>(this: &'static T) -> Self
41 where
42 T: StableAbi + Eq + PartialEq + Debug + Send + Sync + 'static,
43 {
44 Self {
45 ptr: unsafe { RRef::from_raw(this as *const T as *const ErasedObject) },
46 vtable: ConstGenericVTableFor::<T>::VTABLE,
47 }
48 }
49
50 pub fn is_equal(
53 &self,
54 other: &Self,
55 mut checker: TypeCheckerMut<'_>,
56 ) -> Result<bool, ExtraChecksError> {
57 match checker.check_compatibility(self.vtable.layout(), other.vtable.layout()) {
58 ROk(_) => unsafe { Ok(self.vtable.partial_eq()(self.ptr, other.ptr)) },
59 RErr(e) => Err(e),
60 }
61 }
62}
63
64impl Debug for ConstGeneric {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 unsafe { adapt_std_fmt::<ErasedObject>(self.ptr, self.vtable.debug(), f) }
67 }
68}
69
70impl PartialEq for ConstGeneric {
73 fn eq(&self, other: &Self) -> bool {
74 if check_layout_compatibility(self.vtable.layout(), other.vtable.layout()).is_err() {
75 false
76 } else {
77 unsafe { self.vtable.partial_eq()(self.ptr, other.ptr) }
78 }
79 }
80}
81
82impl Eq for ConstGeneric {}
83
84#[repr(C)]
88#[derive(StableAbi)]
89#[sabi(kind(Prefix))]
90#[sabi(missing_field(panic))]
91struct ConstGenericVTable {
92 layout: &'static TypeLayout,
93 partial_eq: unsafe extern "C" fn(RRef<'_, ErasedObject>, RRef<'_, ErasedObject>) -> bool,
94 #[sabi(last_prefix_field)]
95 debug: unsafe extern "C" fn(
96 RRef<'_, ErasedObject>,
97 FormattingMode,
98 &mut RString,
99 ) -> RResult<(), ()>,
100}
101
102struct ConstGenericVTableFor<T>(T);
105
106impl<T> ConstGenericVTableFor<T>
107where
108 T: StableAbi + Eq + PartialEq + Debug + Send + Sync + 'static,
109{
110 const _VTABLE_STATIC: &'static WithMetadata<ConstGenericVTable> = &{
111 WithMetadata::new(ConstGenericVTable {
112 layout: <T as StableAbi>::LAYOUT,
113 partial_eq: partial_eq_impl::<T>,
114 debug: debug_impl::<T>,
115 })
116 };
117
118 const VTABLE: ConstGenericVTable_Ref =
120 ConstGenericVTable_Ref(Self::_VTABLE_STATIC.static_as_prefix());
121}