Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![feature(core_intrinsics)]
- #![feature(raw)]
- #![allow(unused_variables)]
- #![allow(dead_code)]
- use std::any::{Any, TypeId};
- use std::cell::Cell;
- use std::marker::PhantomData;
- use std::raw::TraitObject;
- // Mocks
- pub trait DynamicCast {
- fn __cast<'a>(&'a self, target_type: std::any::TypeId) -> Option<TraitObject>;
- }
- impl DynamicCast {
- pub fn cast<'a, T: ?Sized + 'static>(&'a self) -> Option<&'a T> {
- if let Some(trait_obj) = self.__cast(TypeId::of::<T>()) {
- let value = unsafe {
- *(&trait_obj as *const TraitObject as *const &'a T)
- };
- Some(value)
- }
- else {
- None
- }
- }
- pub fn cast_mut<'a, T: ?Sized + 'static>(&'a mut self) -> Option<&'a mut T> {
- if let Some(mut trait_obj) = self.__cast(TypeId::of::<T>()) {
- let value = {
- &mut trait_obj as *mut TraitObject as *mut &'a mut T
- };
- Some(unsafe { *value })
- }
- else {
- None
- }
- }
- }
- trait Component: Sized + 'static { }
- trait Runable {
- fn run(&self) -> &'static str {
- "Default trait method"
- }
- }
- trait Unrunable {}
- struct DataComponent {
- data: f32
- }
- struct BadComponent {}
- impl Component for DataComponent {}
- impl Component for BadComponent {}
- struct Storage<T: Component> {
- _marker: PhantomData<T>
- }
- impl<T: Component> Storage<T> {
- fn new() -> Self {
- Self {
- _marker: PhantomData
- }
- }
- }
- impl<T: Component> Runable for Storage<T> {
- fn run(&self) -> &'static str {
- "Storage method"
- }
- }
- impl<T: Component> DynamicCast for Storage<T> {
- fn __cast<'a>(&'a self, target: std::any::TypeId) -> Option<std::raw::TraitObject> {
- if target == std::any::TypeId::of::<Runable>() {
- let trait_obj = unsafe {
- std::mem::transmute(self as &'a Runable)
- };
- return Some(trait_obj);
- }
- return None;
- }
- }
- trait Storable: Any + DynamicCast {}
- impl<T> Storable for T
- where T: Any + DynamicCast
- { }
- // Impl
- struct RefCount {
- count: Cell<isize>
- }
- impl RefCount {
- pub fn new() -> Self {
- RefCount {
- count: Cell::new(0)
- }
- }
- pub fn increment_read(&mut self) {
- self.count.set(
- self.count.get() + 1
- );
- }
- pub fn decrement_read(&mut self) {
- self.count.set(
- self.count.get() - 1
- );
- }
- pub fn increment_write(&mut self) {
- self.count.set(
- self.count.get() - 1
- );
- }
- pub fn decrement_write(&mut self) {
- self.count.set(
- self.count.get() + 1
- );
- }
- #[inline]
- pub fn is_write(&self) -> bool {
- self.count.get() < 0
- }
- #[inline]
- pub fn is_read(&self) -> bool {
- self.count.get() > 0
- }
- }
- struct Write<T: Component> {
- any_ptr: *mut Any,
- dyn_ptr: *mut DynamicCast,
- ref_count: RefCount,
- _marker: PhantomData<T>
- }
- impl<T: Component> Write<T> {
- unsafe fn new(any_ptr: *mut Any, dyn_ptr: *mut DynamicCast) -> Self {
- Self {
- any_ptr: any_ptr,
- dyn_ptr: dyn_ptr,
- ref_count: RefCount::new(),
- _marker: PhantomData
- }
- }
- fn downcast<U: 'static>(&self) -> Option<&U> {
- unsafe {
- (&*self.any_ptr).downcast_ref::<U>()
- }
- }
- fn downcast_mut<U: 'static>(&mut self) -> Option<&mut U> {
- unsafe {
- (&mut *self.any_ptr).downcast_mut::<U>()
- }
- }
- fn downcast_dynamic<U: ?Sized + 'static>(&self) -> Option<&U> {
- unsafe {
- (&*self.dyn_ptr).cast::<U>()
- }
- }
- fn downcast_dynamic_mut<U: ?Sized + 'static>(&mut self) -> Option<&mut U> {
- unsafe {
- (&mut *self.dyn_ptr).cast_mut::<U>()
- }
- }
- }
- fn main() {
- let mut value: Storage<DataComponent> = Storage::new();
- let any_ptr = &mut value as *mut _ as *mut Any;
- let dyn_ptr = &mut value as *mut _ as *mut DynamicCast;
- let w: Write<DataComponent> = unsafe { Write::new(any_ptr, dyn_ptr) };
- let r0 = w.downcast_dynamic::<Runable>();
- let r1 = w.downcast_dynamic::<Unrunable>();
- let r2 = w.downcast::<Storage<DataComponent>>();
- let r3 = w.downcast::<Storage<BadComponent>>();
- println!("Type: {:?}, Result: {:?}", type_name(&r0), option_result(&r0));
- println!("Type: {:?}, Result: {:?}", type_name(&r1), option_result(&r1));
- println!("Type: {:?}, Result: {:?}", type_name(&r2), option_result(&r2));
- println!("Type: {:?}, Result: {:?}", type_name(&r3), option_result(&r3));
- println!("{:?}", r0.unwrap().run());
- }
- fn type_name<T>(value: &T) -> &'static str {
- unsafe { std::intrinsics::type_name::<T>() }
- }
- fn option_result<T>(value: &Option<T>) -> &'static str {
- match value {
- Some(_) => "Some",
- None => "None"
- }
- }
Add Comment
Please, Sign In to add comment