use std::any::{Any, TypeId};
use std::marker::PhantomData;
use super::StateId;
#[must_use]
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StateHandle<T> {
pub(crate) state_id: StateId,
pub(crate) _phantom: PhantomData<*mut T>,
}
impl<T> Copy for StateHandle<T> {}
impl<T> Clone for StateHandle<T> {
fn clone(&self) -> Self {
*self
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct StateHandleErased {
state_id: StateId,
type_id: TypeId,
}
impl<T> TryFrom<StateHandleErased> for StateHandle<T>
where
T: Any,
{
type Error = StateHandleErased;
fn try_from(value: StateHandleErased) -> Result<Self, Self::Error> {
if TypeId::of::<T>() == value.type_id {
Ok(Self {
state_id: value.state_id,
_phantom: PhantomData,
})
} else {
Err(value)
}
}
}
impl<T> From<StateHandle<T>> for StateHandleErased
where
T: Any,
{
fn from(value: StateHandle<T>) -> Self {
Self {
state_id: value.state_id,
type_id: TypeId::of::<T>(),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_erasure() {
let handle = StateHandle::<String> {
state_id: StateId::from_raw(0),
_phantom: PhantomData,
};
let handle_erased = StateHandleErased::from(handle);
let handle_good = StateHandle::<String>::try_from(handle_erased);
let handle_bad = StateHandle::<&'static str>::try_from(handle_erased);
assert_eq!(Ok(handle), handle_good);
assert_eq!(Err(handle_erased), handle_bad);
}
}