1use std::any::TypeId;
14use std::fmt::Display;
15use std::fmt::Formatter;
16use std::fmt::Result as FmtResult;
17use std::hash::DefaultHasher;
18use std::hash::Hash as _;
19use std::hash::Hasher;
20
21
22#[macro_export]
30macro_rules! fork_id {
31 () => {{
32 struct _ForkId;
33 &std::string::ToString::to_string(&$crate::ForkId::of(::std::any::TypeId::of::<_ForkId>()))
34 }};
35}
36
37
38#[derive(Clone, Hash, PartialEq, Eq, Debug)]
40pub struct ForkId(TypeId);
41
42impl ForkId {
43 #[doc(hidden)]
44 pub fn of(id: TypeId) -> Self {
45 Self(id)
46 }
47}
48
49impl Display for ForkId {
50 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
51 let mut hasher = DefaultHasher::default();
52 self.0.hash(&mut hasher);
53 write!(f, ":{:016X}", hasher.finish())
54 }
55}
56
57
58#[cfg(test)]
59mod test {
60 use super::*;
61
62
63 #[test]
65 fn ids_for_same_type_are_equal() {
66 struct UniqueType;
67 let id1 = ForkId::of(TypeId::of::<UniqueType>());
68 let id2 = ForkId::of(TypeId::of::<UniqueType>());
69 assert_eq!(id1, id2);
70 assert_eq!(id1.to_string(), id2.to_string());
71 }
72
73 #[test]
74 fn ids_are_actually_distinct() {
75 let id1 = fork_id!();
76 let id2 = fork_id!();
77 assert_ne!(id1, id2);
78 assert_ne!(id1.to_string(), id2.to_string());
79 }
80}