Skip to content

Instantly share code, notes, and snippets.

Created June 13, 2017 00:30
Show Gist options
  • Save anonymous/20402260c354bc51b084039a9816234e to your computer and use it in GitHub Desktop.
Save anonymous/20402260c354bc51b084039a9816234e to your computer and use it in GitHub Desktop.
Shared via Rust Playground
/*
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