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, Debug)]
40pub struct ForkId(TypeId);
41
42impl ForkId {
43 #[allow(missing_docs)]
44 #[doc(hidden)]
45 pub fn of(id: TypeId) -> Self {
46 ForkId(id)
47 }
48}
49
50impl Display for ForkId {
51 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
52 let mut hasher = DefaultHasher::default();
53 self.0.hash(&mut hasher);
54 write!(f, ":{:016X}", hasher.finish())
55 }
56}
57
58
59#[cfg(test)]
60mod test {
61 use super::*;
62
63
64 #[test]
66 fn ids_for_same_type_are_equal() {
67 struct UniqueType;
68 let id1 = ForkId::of(TypeId::of::<UniqueType>());
69 let id2 = ForkId::of(TypeId::of::<UniqueType>());
70 assert_eq!(id1, id2);
71 assert_eq!(id1.to_string(), id2.to_string());
72 }
73
74 #[test]
75 fn ids_are_actually_distinct() {
76 let id1 = fork_id!();
77 let id2 = fork_id!();
78 assert_ne!(id1, id2);
79 assert_ne!(id1.to_string(), id2.to_string());
80 }
81}