Skip to content

Instantly share code, notes, and snippets.

@KodrAus
Created February 2, 2020 09:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KodrAus/3acc42446ad75123c58d14f56f7cc524 to your computer and use it in GitHub Desktop.
Save KodrAus/3acc42446ad75123c58d14f56f7cc524 to your computer and use it in GitHub Desktop.
#![feature(unsize)]
use std::{
any::TypeId,
marker::Unsize,
fmt,
};
enum Dyn<'v, T: ?Sized, TStatic: ?Sized>
{
NonDowncastable(&'v T),
Downcastable(TypeId, &'v TStatic),
}
impl<'v, T: ?Sized, TStatic: ?Sized> Clone for Dyn<'v, T, TStatic> {
fn clone(&self) -> Self {
match *self {
Dyn::NonDowncastable(value) => Dyn::NonDowncastable(value),
Dyn::Downcastable(type_id, value) => Dyn::Downcastable(type_id, value),
}
}
}
impl<'v, T: ?Sized, TStatic: ?Sized> Copy for Dyn<'v, T, TStatic> { }
impl<'v, T, TStatic> Dyn<'v, T, TStatic>
where
T: ?Sized + 'v,
TStatic: ?Sized + Unsize<T> + 'static,
{
fn new_downcastable<U>(value: &'v U) -> Self
where
U: Unsize<TStatic> + 'static,
{
Dyn::Downcastable(TypeId::of::<U>(), value)
}
fn new_non_downcastable<U>(value: &'v U) -> Self
where
U: Unsize<T>,
{
Dyn::NonDowncastable(value)
}
fn get(self) -> &'v T {
match self {
Dyn::NonDowncastable(value) => value,
Dyn::Downcastable(_, value) => value,
}
}
fn try_downcast_ref<U>(self) -> Option<&'v U>
where
U: 'static,
{
if let Dyn::Downcastable(type_id, value) = self {
if TypeId::of::<U>() == type_id {
return Some(unsafe { &*(value as *const TStatic as *const U) })
}
}
None
}
}
type DynDebug<'v> = Dyn<'v, dyn fmt::Debug, dyn fmt::Debug + 'static>;
fn main() {
let d = DynDebug::new_downcastable(&42i32);
let u = DynDebug::new_non_downcastable(&42i32);
println!("{:?}: {:?}", d.get(), d.try_downcast_ref::<i32>());
println!("{:?}: {:?}", u.get(), u.try_downcast_ref::<i32>());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment