use std::any::TypeId;
use std::borrow::Borrow;
use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use crate::logical::{Registered, RegistryEntry, RegistryExt};
use crate::logical::registry::Registry;
use crate::raw::{RegistrationId as RawRegistrationId, RegistryEntry as RawRegistryEntry};
pub struct RegistrationId<R: Registry + ?Sized> {
raw_id: RawRegistrationId,
registry_index: usize,
registry: PhantomData<fn(R)>
}
impl<R: Registry + ?Sized> RegistrationId<R> {
pub(crate) fn new(
raw_index: usize,
registry_index: usize
) -> Self {
Self {
raw_id: RawRegistrationId::new(raw_index),
registry_index,
registry: PhantomData
}
}
#[allow(dead_code)]
pub(crate) fn raw(self) -> RawRegistrationId {
self.raw_id
}
pub fn index(self) -> usize {
self.registry_index
}
pub fn entry(self) -> RegistryEntry<R> {
unsafe { RegistryEntry::new_unchecked(self.raw_id.entry()) }
}
pub fn metadata(self) -> &'static R::TypeInfo {
self.entry().type_info()
}
pub fn of<T: Registered<R> + ?Sized>() -> Self {
unsafe {
Self::from_type_id_unchecked(TypeId::of::<T>())
}
}
pub(crate) unsafe fn from_raw_entry_unchecked(raw_entry: &RawRegistryEntry) -> Self {
Self::from_type_id_unchecked(raw_entry.type_id())
}
pub(crate) unsafe fn from_type_id_unchecked(type_id: TypeId) -> Self {
*R::index::<RawRegistryEntry>().get(&type_id).expect("type is registered")
}
}
impl<R: Registry + ?Sized> Clone for RegistrationId<R> {
fn clone(&self) -> Self {
Self::new(self.raw_id.index(), self.registry_index)
}
}
impl<R: Registry + ?Sized> Copy for RegistrationId<R> {}
impl<R: Registry + ?Sized> Debug for RegistrationId<R> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct(&format!("RegistrationId<{}>", std::any::type_name::<R>()))
.field("raw_id", &self.raw_id)
.field("registry_index", &self.registry_index)
.field("registry", &R::name())
.finish()
}
}
impl<R: Registry + ?Sized> PartialEq for RegistrationId<R> {
fn eq(&self, other: &Self) -> bool {
self.raw_id == other.raw_id
}
}
impl<R: Registry + ?Sized> Eq for RegistrationId<R> {}
impl<R: Registry + ?Sized> Hash for RegistrationId<R> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.raw_id.hash(state)
}
}
impl<R: Registry + ?Sized> Display for RegistrationId<R> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let index = self.registry_index;
let name = R::name();
f.write_fmt(format_args!("'{name}' registration ID #{index}"))
}
}
impl<R: Registry + ?Sized> From<RegistrationId<R>> for RawRegistrationId {
fn from(value: RegistrationId<R>) -> Self {
value.raw_id
}
}
impl<R: Registry + ?Sized> PartialEq<RawRegistrationId> for RegistrationId<R> {
fn eq(&self, other: &RawRegistrationId) -> bool {
&self.raw_id == other
}
}
impl<R: Registry + ?Sized> PartialEq<RegistrationId<R>> for RawRegistrationId {
fn eq(&self, other: &RegistrationId<R>) -> bool {
self == &other.raw_id
}
}
impl<R: Registry + ?Sized> Borrow<RawRegistrationId> for RegistrationId<R> {
fn borrow(&self) -> &RawRegistrationId {
&self.raw_id
}
}