Created
June 13, 2017 00:30
-
-
Save anonymous/20402260c354bc51b084039a9816234e to your computer and use it in GitHub Desktop.
Shared via Rust Playground
This file contains 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
/* | |
This pattern was inspired by the following docs from the Rust SDL2 library. | |
https://docs.rs/sdl2/0.30.0/sdl2/render/struct.TextureCreator.html | |
> Any Texture created here can only be drawn onto the original Canvas. | |
> A Texture used in a Canvas must come from a TextureCreator coming | |
> from that same Canvas. Using a Texture to render to a Canvas not | |
> being the parent of the Texture's TextureCreator is undefined behavior. | |
Can we make an API where it is impossible to use a Texture with the wrong Canvas? | |
NOTE: I doubt this idea is novel, I'm just not sure what to search for. | |
*/ | |
#![feature(conservative_impl_trait)] | |
#[macro_use] | |
mod render { | |
use std::marker::PhantomData; | |
#[derive(Default)] | |
struct CanvasData<T> { | |
phantom_id: PhantomData<T>, | |
} | |
#[derive(Default)] | |
struct TextureData<T> { | |
phantom_id: PhantomData<T>, | |
} | |
pub trait Texture { | |
// just to keep things cohesive. | |
} | |
impl<T> Texture for TextureData<T> {} | |
pub trait Canvas { | |
type Texture: Texture; | |
fn create_texture(&self)->Self::Texture; | |
fn draw_texture(&mut self, _texture: &Self::Texture); | |
} | |
impl <T> Canvas for CanvasData<T> { | |
type Texture = TextureData<T>; | |
fn create_texture(&self) -> Self::Texture { | |
TextureData::<T>{phantom_id: PhantomData} | |
} | |
fn draw_texture(&mut self, _texture: &Self::Texture){ | |
//do nothing | |
} | |
} | |
pub unsafe fn new_canvas<T: Default>() -> impl Canvas { | |
<CanvasData<T> as Default>::default() | |
} | |
#[macro_export] | |
macro_rules! new_canvas { | |
() => {{ | |
#[derive(Default)] | |
struct _CanvasID; | |
unsafe {new_canvas::<_CanvasID>()} | |
}}; | |
($name: ident) => {{ | |
#[derive(Default)] | |
struct $name; | |
unsafe {new_canvas::<$name>()} | |
}} | |
} | |
} | |
use render::*; | |
fn main() { | |
let mut c1 = new_canvas!(C1); | |
let t1 = c1.create_texture(); | |
c1.draw_texture(&t1); | |
let mut c2 = new_canvas!(C2); | |
let t2 = c2.create_texture(); | |
c2.draw_texture(&t2); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment