1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std::{
any::TypeId,
hash::{Hash, Hasher},
mem,
sync::atomic::AtomicUsize,
};
use crate::EXECUTABLE_IDENTITY;
pub extern "C" fn new_utypeid<T>() -> UTypeId
where
T: 'static,
{
UTypeId::new::<T>()
}
#[repr(C)]
#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Copy, Clone, Hash, StableAbi)]
#[sabi(inside_abi_stable_crate)]
pub struct UTypeId {
executable_identity: *const AtomicUsize,
type_id_array: [u8; MAX_TYPE_ID_SIZE],
}
impl UTypeId {
#[inline(always)]
pub fn new<T>() -> Self
where
T: 'static,
{
Self {
executable_identity: &EXECUTABLE_IDENTITY,
type_id_array: get_typeid::<T>(),
}
}
}
type TypeIdArray = [u8; mem::size_of::<TypeId>()];
const MAX_TYPE_ID_SIZE: usize = 16;
#[inline(always)]
fn get_typeid<T: 'static>() -> [u8; MAX_TYPE_ID_SIZE] {
let mut hasher = TypeIdHasher {
value: [0; MAX_TYPE_ID_SIZE],
written: 0,
};
TypeId::of::<T>().hash(&mut hasher);
hasher.value
}
#[derive(Default)]
struct TypeIdHasher {
value: [u8; MAX_TYPE_ID_SIZE],
written: usize,
}
impl TypeIdHasher {
#[inline(never)]
#[cold]
fn overflow_msg() -> ! {
eprintln!(
"TypeId requires writing more than {} bytes to the hasher.",
MAX_TYPE_ID_SIZE
);
::std::process::abort();
}
}
impl Hasher for TypeIdHasher {
#[inline(always)]
fn write(&mut self, bytes: &[u8]) {
let _: [u8; MAX_TYPE_ID_SIZE - mem::size_of::<TypeId>()];
if bytes.len() == mem::size_of::<TypeId>() {
unsafe {
let into = (&mut self.value) as *mut _ as *mut TypeIdArray;
let from = bytes.as_ptr() as *const TypeIdArray;
*into = *from;
}
self.written = mem::size_of::<TypeId>();
return;
}
let old_pos = self.written;
self.written += bytes.len();
if self.written <= MAX_TYPE_ID_SIZE {
self.value[old_pos..self.written].copy_from_slice(bytes);
} else {
Self::overflow_msg()
}
}
#[inline(always)]
fn finish(&self) -> u64 {
0
}
}