Skip to content

Instantly share code, notes, and snippets.

@rust-play
Created February 8, 2021 14:57
Show Gist options
  • Save rust-play/ac646af496c7984e90c003f5f12c2d55 to your computer and use it in GitHub Desktop.
Save rust-play/ac646af496c7984e90c003f5f12c2d55 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
use std::any::{Any, TypeId};
use std::fmt::Debug;
pub trait Resource: Any + Debug {
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