Last active
April 9, 2016 02:40
-
-
Save Sgeo/3d7f8449ea5ba136038a9c677e744004 to your computer and use it in GitHub Desktop.
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
#![allow(dead_code)] | |
use std::marker::PhantomData; | |
use std::sync::atomic::{Ordering, AtomicUsize, ATOMIC_USIZE_INIT}; | |
static mut STORED: [usize; 256] = [0; 256]; | |
static NEXT: AtomicUsize = ATOMIC_USIZE_INIT; | |
fn store<T>(t: T) -> u8 { | |
unsafe { | |
let stored_addr = NEXT.fetch_add(1, Ordering::SeqCst); | |
if stored_addr >= 256 { | |
panic!("More than 256 items store()d!"); | |
} | |
let real_addr = Box::into_raw(Box::new(t)) as usize; | |
println!("storing real_addr {}", real_addr); | |
STORED[stored_addr] = real_addr; | |
stored_addr as u8 | |
} | |
} | |
unsafe fn fetch<T>(stored_addr: u8) -> &'static T { | |
&*(STORED[stored_addr as usize] as *const T) | |
} | |
trait Num { | |
fn num() -> u8; | |
} | |
unsafe trait Reifies<T>: Num { | |
fn reflect() -> &'static T { | |
unsafe { | |
fetch(Self::num()) | |
} | |
} | |
} | |
macro_rules! num { | |
($name:ident, $val:expr) => { | |
struct $name; | |
impl Num for $name { | |
fn num() -> u8 { | |
$val | |
} | |
} | |
} | |
} | |
num!(Ox0, 0x0); | |
num!(Ox1, 0x1); | |
num!(Ox2, 0x2); | |
num!(Ox3, 0x3); | |
num!(Ox4, 0x4); | |
num!(Ox5, 0x5); | |
num!(Ox6, 0x6); | |
num!(Ox7, 0x7); | |
num!(Ox8, 0x8); | |
num!(Ox9, 0x9); | |
num!(OxA, 0xA); | |
num!(OxB, 0xB); | |
num!(OxC, 0xC); | |
num!(OxD, 0xD); | |
num!(OxE, 0xE); | |
num!(OxF, 0xF); | |
struct Byte<H, L>(PhantomData<(H, L)>); | |
impl<H: Num, L: Num> Num for Byte<H, L> { | |
fn num() -> u8 { | |
(H::num() << 4) + L::num() | |
} | |
} | |
unsafe impl<T, H: Num, L: Num> Reifies<T> for Byte<H, L> {} | |
trait AcceptReifies<T> { | |
type Result; | |
fn call<P: Reifies<T>>(self) -> Self::Result; | |
} | |
fn reify<T, F: AcceptReifies<T>>(t: T, f: F) -> F::Result { | |
let addr = store(t); | |
fn part1<T, F: AcceptReifies<T>>(addr: u8, f: F) -> F::Result { | |
let low = 0x0F & addr; | |
match low { | |
0x0 => part2::<Ox0, _, _>(addr, f), | |
0x1 => part2::<Ox1, _, _>(addr, f), | |
0x2 => part2::<Ox2, _, _>(addr, f), | |
0x3 => part2::<Ox3, _, _>(addr, f), | |
0x4 => part2::<Ox4, _, _>(addr, f), | |
0x5 => part2::<Ox5, _, _>(addr, f), | |
0x6 => part2::<Ox6, _, _>(addr, f), | |
0x7 => part2::<Ox7, _, _>(addr, f), | |
0x8 => part2::<Ox8, _, _>(addr, f), | |
0x9 => part2::<Ox9, _, _>(addr, f), | |
0xA => part2::<OxA, _, _>(addr, f), | |
0xB => part2::<OxB, _, _>(addr, f), | |
0xC => part2::<OxC, _, _>(addr, f), | |
0xD => part2::<OxD, _, _>(addr, f), | |
0xE => part2::<OxE, _, _>(addr, f), | |
0xF => part2::<OxF, _, _>(addr, f), | |
_ => unreachable!() | |
} | |
} | |
fn part2<Low: Num, T, F: AcceptReifies<T>>(addr: u8, f: F) -> F::Result { | |
let high = addr >> 4; | |
match high { | |
0x0 => f.call::<Byte<Ox0, Low>>(), | |
0x1 => f.call::<Byte<Ox1, Low>>(), | |
0x2 => f.call::<Byte<Ox2, Low>>(), | |
0x3 => f.call::<Byte<Ox3, Low>>(), | |
0x4 => f.call::<Byte<Ox4, Low>>(), | |
0x5 => f.call::<Byte<Ox5, Low>>(), | |
0x6 => f.call::<Byte<Ox6, Low>>(), | |
0x7 => f.call::<Byte<Ox7, Low>>(), | |
0x8 => f.call::<Byte<Ox8, Low>>(), | |
0x9 => f.call::<Byte<Ox9, Low>>(), | |
0xA => f.call::<Byte<OxA, Low>>(), | |
0xB => f.call::<Byte<OxB, Low>>(), | |
0xC => f.call::<Byte<OxC, Low>>(), | |
0xD => f.call::<Byte<OxD, Low>>(), | |
0xE => f.call::<Byte<OxE, Low>>(), | |
0xF => f.call::<Byte<OxF, Low>>(), | |
_ => unreachable!() | |
} | |
} | |
part1(addr, f) | |
} | |
struct MyAccept; | |
impl AcceptReifies<i32> for MyAccept { | |
type Result = (); | |
fn call<P: Reifies<i32>>(self) { | |
println!("MyAccept given addr: {}", P::reflect() as *const i32 as usize); | |
println!("Reflected value: {}", P::reflect()); | |
} | |
} | |
macro_rules! ar { | |
($arg:ty => $ret:ty, $closure:expr) => {{ | |
struct This; | |
impl AcceptReifies<$arg> for This { | |
type Result = $ret; | |
fn call<P: Reifies<$arg>>(self) -> Self::Result { | |
$closure() | |
} | |
} | |
This | |
}}; | |
($arg:ty, $closure:expr) => {ar!($arg => (), $closure)}; | |
} | |
fn main() { | |
reify(12345, MyAccept); | |
let s = String::from("Hello there!"); | |
reify(s, ar!(String, || println!("{}", P::reflect()))); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment