Skip to content

Instantly share code, notes, and snippets.

@ascjones
Last active November 16, 2020 10:39
Show Gist options
  • Save ascjones/e3f82327a4a6653419615c7f7d5b9a53 to your computer and use it in GitHub Desktop.
Save ascjones/e3f82327a4a6653419615c7f7d5b9a53 to your computer and use it in GitHub Desktop.
use std::any;
struct Type;
trait TypeInfo {
fn type_info() -> Type;
fn wrapped_type_id() -> Option<any::TypeId> {
None
}
}
impl TypeInfo for u32 {
fn type_info() -> Type {
Type
}
}
impl<T> TypeInfo for Box<T>
where
T: TypeInfo + 'static
{
fn type_info() -> Type {
T::type_info()
}
fn wrapped_type_id() -> Option<any::TypeId> {
Some(any::TypeId::of::<T>())
}
}
fn type_id<T>() -> any::TypeId
where
T: TypeInfo + 'static,
{
match T::wrapped_type_id() {
None => any::TypeId::of::<T>(),
Some(id) => id,
}
}
fn main() {
println!("{:?} {:?}", type_id::<u32>(), type_id::<Box<u32>>())
}
use std::any;
use std::marker::PhantomData;
struct Type;
trait TypeInfo {
fn type_info() -> Type;
}
impl TypeInfo for u32 {
fn type_info() -> Type {
Type
}
}
impl<T> TypeInfo for Box<T>
where
T: TypeInfo + 'static
{
fn type_info() -> Type {
T::type_info()
}
}
impl<T: ?Sized> scale::WrapperTypeEncode for Box<T> {}
struct MetaType {
type_id: any::TypeId,
fn_type_info: fn() -> Type
}
mod scale {
use std::ops::Deref;
pub trait WrapperTypeEncode: Deref {}
}
impl MetaType {
pub fn new<T>() -> Self
where
T: TypeInfo + ?Sized + 'static,
{
Self {
fn_type_info: <T as TypeInfo>::type_info,
type_id: any::TypeId::of::<T>(),
}
}
pub fn new_deref<T, U>() -> Self
where
T: scale::WrapperTypeEncode<Target = U>,
U: TypeInfo + ?Sized + 'static,
{
Self {
fn_type_info: <U as TypeInfo>::type_info,
type_id: any::TypeId::of::<U>(),
}
}
}
///
struct TypeInfoTag<T>(PhantomData<T>);
trait TypeInfoKind {
type Type: TypeInfo + 'static;
#[inline]
fn kind(&self) -> TypeInfoTag<Self::Type> {
TypeInfoTag(PhantomData)
}
}
impl<T: TypeInfo + 'static> TypeInfoTag<T> {
#[inline]
fn new(self) -> MetaType {
MetaType::new::<T>()
}
}
// Requires one extra autoref to call! Lower priority than WrapperTypeKind.
impl<T: TypeInfo + 'static> TypeInfoKind for &PhantomData<T> {
type Type = T;
}
///
struct WrapperTypeTag<T>(PhantomData<T>);
trait WrapperTypeKind {
type Type: scale::WrapperTypeEncode<Target = Self::Target>;
type Target: TypeInfo + 'static;
#[inline]
fn kind(&self) -> WrapperTypeTag<Self::Type> {
WrapperTypeTag(PhantomData)
}
}
// Does not require any autoref if called as (&error).anyhow_kind().
impl<T: scale::WrapperTypeEncode<Target = U>, U: TypeInfo + 'static> WrapperTypeKind for PhantomData<T> {
type Type = T;
type Target = U;
}
impl<T: scale::WrapperTypeEncode<Target = U>, U: TypeInfo + 'static> WrapperTypeTag<T> {
#[inline]
fn new(self) -> MetaType {
MetaType::new_deref::<T, U>()
}
}
macro_rules! meta_type {
($meta_type:ty) => ({
#[allow(unused_imports)]
use $crate::{TypeInfoKind, WrapperTypeKind};
let meta_type = PhantomData::<$meta_type>;
(&meta_type).kind().new()
});
}
fn main() {
let ty = meta_type!(u32);
let ty2 = meta_type!(Box<u32>);
println!("{:?} {:?}", ty.type_id, ty2.type_id)
}
use std::any;
struct Type;
trait TypeInfo {
type Type: 'static;
fn type_info() -> Type;
}
impl TypeInfo for u32 {
type Type = Self;
fn type_info() -> Type {
Type
}
}
impl<T> TypeInfo for Box<T>
where
T: TypeInfo + 'static
{
type Type = T;
fn type_info() -> Type {
T::type_info()
}
}
fn type_id<T>() -> any::TypeId
where
T: TypeInfo + 'static,
{
any::TypeId::of::<T::Type>()
}
fn main() {
println!("{:?} {:?}", type_id::<u32>(), type_id::<Box<u32>>())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment