use std::{ fmt::Debug, hash::{Hash, Hasher}, }; use std::{any::TypeId, marker::PhantomData}; use uuid::Uuid; #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub struct HandleId(pub Uuid); pub const DEFAULT_HANDLE_ID: HandleId = HandleId(Uuid::from_u128(240940089166493627844978703213080810552)); impl HandleId { pub fn new() -> HandleId { HandleId(Uuid::new_v4()) } } pub struct Handle { pub id: HandleId, marker: PhantomData, } impl Handle { pub fn new() -> Self { Handle { id: HandleId::new(), marker: PhantomData, } } pub const fn from_id(id: HandleId) -> Self { Handle { id, marker: PhantomData, } } pub const fn from_u128(value: u128) -> Self { Handle { id: HandleId(Uuid::from_u128(value)), marker: PhantomData, } } pub const fn from_bytes(bytes: [u8; 16]) -> Self { Handle { id: HandleId(Uuid::from_bytes(bytes)), marker: PhantomData, } } pub fn from_untyped(untyped_handle: HandleUntyped) -> Option> where T: 'static, { if TypeId::of::() == untyped_handle.type_id { Some(Handle::from_id(untyped_handle.id)) } else { None } } } impl From for Handle { fn from(value: HandleId) -> Self { Handle::from_id(value) } } impl From for Handle { fn from(value: u128) -> Self { Handle::from_u128(value) } } impl From<[u8; 16]> for Handle { fn from(value: [u8; 16]) -> Self { Handle::from_bytes(value) } } impl From for Handle where T: 'static, { fn from(handle: HandleUntyped) -> Self { if TypeId::of::() == handle.type_id { Handle { id: handle.id, marker: PhantomData::default(), } } else { panic!("attempted to convert untyped handle to incorrect typed handle") } } } impl Hash for Handle { fn hash(&self, state: &mut H) { self.id.hash(state); } } impl PartialEq for Handle { fn eq(&self, other: &Self) -> bool { self.id == other.id } } impl Eq for Handle {} impl Debug for Handle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { let name = std::any::type_name::().split("::").last().unwrap(); write!(f, "Handle<{}>({:?})", name, self.id.0) } } impl Default for Handle { fn default() -> Self { Handle { id: DEFAULT_HANDLE_ID, marker: PhantomData, } } } impl Clone for Handle { fn clone(&self) -> Self { Handle { id: self.id.clone(), marker: PhantomData, } } } impl Copy for Handle {} #[derive(Hash, Copy, Clone, Eq, PartialEq, Debug)] pub struct HandleUntyped { pub id: HandleId, pub type_id: TypeId, } impl HandleUntyped { pub fn is_handle(untyped: &HandleUntyped) -> bool { TypeId::of::() == untyped.type_id } } impl From> for HandleUntyped where T: 'static, { fn from(handle: Handle) -> Self { HandleUntyped { id: handle.id, type_id: TypeId::of::(), } } }