-
-
Save jpastuszek/06b5dc4d3ab267c0f7a0d379a415c199 to your computer and use it in GitHub Desktop.
Using vtable dispatch to work with owned type behind Box<dyn> trait
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::any::{Any, TypeId}; | |
use std::fmt::Debug; | |
pub trait Resource: Any + Debug { | |
// this returns correct function for the Self to work on Box so that it can be casted and unboxed | |
fn combine_fn(&self) -> fn(left: Box<dyn Resource>, right: Box<dyn Resource>) -> Box<dyn Resource>; | |
} | |
#[derive(Debug)] | |
struct File(u32); | |
impl File { | |
fn combine(left: File, right: File) -> File { | |
File(left.0 + right.0) | |
} | |
} | |
// taken from Box::downcast as I cannot cast Box<dyn Resource> to Box<dyn Any> | |
// https://github.com/rust-lang/rfcs/issues/2765#issuecomment-703950666 | |
pub fn downcast<T: Resource>(res: Box<dyn Resource>) -> Result<Box<T>, Box<dyn Resource>> { | |
if <dyn Resource>::type_id(&*res) == TypeId::of::<T>() { | |
unsafe { | |
let raw: *mut (dyn Resource) = Box::into_raw(res); | |
Ok(Box::from_raw(raw as *mut T)) | |
} | |
} else { | |
Err(res) | |
} | |
} | |
impl Resource for File { | |
fn combine_fn(&self) -> fn(left: Box<dyn Resource>, right: Box<dyn Resource>) -> Box<dyn Resource> { | |
fn dyn_combine(left: Box<dyn Resource>, right: Box<dyn Resource>) -> Box<dyn Resource> { | |
let left: File = *downcast::<File>(left).unwrap(); | |
let right: File = *downcast::<File>(right).unwrap(); | |
Box::new(File::combine(left, right)) | |
} | |
dyn_combine | |
} | |
} | |
fn main() { | |
let a = File(1); | |
let b = File(10); | |
let a: Box<dyn Resource> = Box::new(a); | |
let b: Box<dyn Resource> = Box::new(b); | |
let c = a.combine_fn()(a,b); | |
dbg![c]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment