abi_stable/std_types/
utypeid.rs
1use std::{
6 any::TypeId,
7 hash::{Hash, Hasher},
8 mem,
9 sync::atomic::AtomicUsize,
10};
11
12use crate::{sabi_types::MaybeCmp, EXECUTABLE_IDENTITY};
13
14pub extern "C" fn new_utypeid<T>() -> UTypeId
38where
39 T: 'static,
40{
41 UTypeId::new::<T>()
42}
43
44#[doc(hidden)]
45pub extern "C" fn some_utypeid<T>() -> MaybeCmp<UTypeId>
46where
47 T: 'static,
48{
49 MaybeCmp::Just(UTypeId::new::<T>())
50}
51
52#[doc(hidden)]
53#[allow(clippy::missing_const_for_fn)]
54pub extern "C" fn no_utypeid() -> MaybeCmp<UTypeId> {
55 MaybeCmp::Nothing
56}
57
58#[repr(C)]
75#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Copy, Clone, Hash, StableAbi)]
76pub struct UTypeId {
77 executable_identity: *const AtomicUsize,
79 type_id_array: [u8; MAX_TYPE_ID_SIZE],
82}
83
84unsafe impl Send for UTypeId {}
85unsafe impl Sync for UTypeId {}
86
87impl UTypeId {
88 #[inline(always)]
100 pub fn new<T>() -> Self
101 where
102 T: 'static,
103 {
104 Self {
105 executable_identity: &EXECUTABLE_IDENTITY,
106 type_id_array: get_typeid::<T>(),
107 }
108 }
109}
110
111type TypeIdArray = [u8; mem::size_of::<TypeId>()];
114
115const MAX_TYPE_ID_SIZE: usize = 16;
116
117#[inline(always)]
118fn get_typeid<T: 'static>() -> [u8; MAX_TYPE_ID_SIZE] {
119 let mut hasher = TypeIdHasher {
120 value: [0; MAX_TYPE_ID_SIZE],
121 written: 0,
122 };
123 TypeId::of::<T>().hash(&mut hasher);
124 hasher.value
125}
126
127#[derive(Default)]
128struct TypeIdHasher {
129 value: [u8; MAX_TYPE_ID_SIZE],
130 written: usize,
131}
132
133impl TypeIdHasher {
134 #[inline(never)]
135 #[cold]
136 fn overflow_msg() -> ! {
137 eprintln!(
138 "TypeId requires writing more than {} bytes to the hasher.",
139 MAX_TYPE_ID_SIZE
140 );
141 ::std::process::abort();
142 }
143}
144
145impl Hasher for TypeIdHasher {
146 #[inline(always)]
147 fn write(&mut self, bytes: &[u8]) {
148 let _: [u8; MAX_TYPE_ID_SIZE - mem::size_of::<TypeId>()];
149 if bytes.len() == mem::size_of::<TypeId>() {
150 unsafe {
151 let into = (&mut self.value) as *mut _ as *mut TypeIdArray;
152 let from = bytes.as_ptr() as *const TypeIdArray;
153 *into = *from;
154 }
155 self.written = mem::size_of::<TypeId>();
156 return;
157 }
158 let old_pos = self.written;
159 self.written += bytes.len();
160 if self.written <= MAX_TYPE_ID_SIZE {
161 self.value[old_pos..self.written].copy_from_slice(bytes);
162 } else {
163 Self::overflow_msg()
164 }
165 }
166
167 #[inline(always)]
168 fn finish(&self) -> u64 {
169 0
171 }
172}