Skip to content

Instantly share code, notes, and snippets.

Created June 30, 2017 05:06
Show Gist options
  • Save anonymous/a52a37d5bdf6335d3a3dd09caa6bac9c to your computer and use it in GitHub Desktop.
Save anonymous/a52a37d5bdf6335d3a3dd09caa6bac9c to your computer and use it in GitHub Desktop.
Rust code shared from the playground
#![feature(optin_builtin_traits)]
mod userspace {
use unit::Unit;
use session::{Ai, DataTrait, Session};
#[derive(Debug)]
struct MyAi();
#[derive(Debug)]
struct MyData<'a>{
units: Vec<&'a mut Unit>
}
impl<'a> Default for MyData<'a>{
fn default() -> MyData<'a>{
MyData{units: vec![]}
}
}
impl<'a> DataTrait<'a> for MyData<'a> {}
impl<'a> Ai<'a> for MyAi where MyData<'a>: 'static + ::std::fmt::Debug {
type Data = MyData<'a>;
fn on_unit_show<'b>(&mut self, data: &'b mut Self::Data, unit: &'a mut Unit) {
println!("On unit show. Unit: {:?}", unit);
//::std::thread::spawn(move || {let _ = unit;}); //`unit::Unit` cannot be sent between threads safely
data.units.push(unit);
}
fn on_frame<'b>(&mut self, data: &'b mut Self::Data) {
println!("On frame. Data: {:?}", data);
}
fn on_start<'b>(&mut self, _data: &'b mut Self::Data) {
println!("On start");
}
fn on_end<'b>(&mut self, _data: &'b mut Self::Data) {
println!("On end");
}
}
pub fn start() {
Session::new(MyAi()).setup();
}
}
use unit::Unit;
use session::handler::Handler;
extern fn raw_unit_show(unit: *mut Unit) {
Handler::with(|callbacks| callbacks.on_unit_show(unit));
}
extern fn raw_on_frame() {
Handler::with(|callbacks| callbacks.on_frame());
}
extern fn raw_on_start() {
Handler::with(|callbacks| callbacks.on_start());
}
extern fn raw_on_end() {
Handler::with(|callbacks| callbacks.on_end());
}
fn main () {
userspace::start();
//raw_on_frame(); //thread 'main' panicked at 'Data dropped', /checkout/src/libcore/option.rs:823
raw_on_start(); //On start
let u = Box::new(Unit(333));
raw_unit_show(Box::into_raw(u)); //On unit show. Unit: Unit(333)
raw_on_frame(); //On frame. Data: MyData { units: [Unit(333)] }
raw_on_end(); //On end
//raw_on_frame(); //thread 'main' panicked at 'Data dropped', /checkout/src/libcore/option.rs:794
raw_on_start(); //On start
raw_on_frame(); //On frame. Data: MyData { units: [] }
}
//where D: ::std::fmt::Debug
mod unit {
#[derive(Debug)]
pub struct Unit(pub i32);
//use std::marker::Sync;
//use std::marker::Send;
impl !Sync for Unit{}
impl !Send for Unit{}
}
mod session {
use unit::Unit;
use std::marker::PhantomData;
pub trait DataTrait<'a>: Default {
}
#[derive(Debug)]
pub struct Session<'a, D: 'static + DataTrait<'a>, A:Ai<'a, Data=D>> {
data: Option<Box<D>>,
ai: A,
_p: PhantomData<&'a ()>
}
#[allow(unused_variables)]
pub trait Ai<'a>{
type Data: 'static + DataTrait<'a>;
fn on_unit_show<'b>(&mut self, data: &'b mut Self::Data, unit: &'a mut Unit) {}
fn on_frame<'b>(&mut self, data: &'b mut Self::Data) {}
fn on_start<'b>(&mut self, data: &'b mut Self::Data) {}
fn on_end<'b>(&mut self, data: &'b mut Self::Data) {}
}
pub trait Callbacks {
fn on_unit_show(&mut self, unit: *mut Unit);
fn on_frame(&mut self);
fn on_start(&mut self);
fn on_end(&mut self);
}
pub mod handler {
use super::Callbacks;
use std::cell::Cell;
thread_local! {
static HANDLER: Handler = Handler::new();
}
pub struct Handler {
inner: Cell<Option<Box<Callbacks>>>
}
impl Handler {
fn new() -> Self {
Handler {
inner: Cell::new(None)
}
}
pub fn set<T: 'static + Callbacks>(callbacks: Box<T>) {
HANDLER.with(|handler| {
handler.inner.set(Some(callbacks));
});
}
pub fn _clear(&self) {
HANDLER.with(|handler| {
handler.inner.set(None);
});
}
pub fn with<F:FnOnce(&mut Callbacks)>(f: F) {
HANDLER.with(|handler| {
let mut callbacks = handler.inner.take().expect("Callbacks didn't set");
f(&mut *callbacks);
handler.inner.set(Some(callbacks))
});
}
}
}
impl<'a, D: 'static + DataTrait<'a>, A:Ai<'a, Data=D>> Callbacks for Session<'a, D, A> where Session<'a, D, A>: 'static {
fn on_unit_show(&mut self, unit: *mut Unit) {
let unit: &'a mut Unit = unsafe{&mut *unit};
self.with_components(move |data, ai| ai.on_unit_show(data, unit));
}
fn on_frame(&mut self) {
self.with_components(move |data, ai| ai.on_frame(data));
}
fn on_start(&mut self) {
self.data = Some(Box::new(<D as Default>::default()));
self.with_components(move |data, ai| ai.on_start(data));
}
fn on_end(&mut self) {
self.with_components(move |data, ai| ai.on_end(data));
self.data = None;
}
}
impl<'a, D: 'static + DataTrait<'a>, A:Ai<'a, Data=D>> Session<'a, D, A> where Session<'a, D, A>: 'static {
pub fn new(ai: A) -> Self {
Session{data: None, ai, _p: PhantomData}
}
fn components(&mut self) -> (&mut D, &mut A) {
(
&mut *self.data.as_mut().expect("Data dropped"),
&mut self.ai
)
}
fn with_components<F:FnOnce(&mut D, &mut A)>(&mut self, f: F) {
let (data, ai) = self.components();
f(data, ai);
}
pub fn setup(self) {
handler::Handler::set(Box::new(self));
}
//fn raw_unit_show(unit: *mut Unit) {
//let unit: &mut Unit = unsafe{&mut *unit};
//self.ai.unit_show(&mut game, unit);
//}).unwrap();
//}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment