Skip to content

Instantly share code, notes, and snippets.

@Sgeo
Last active April 9, 2016 02:40
Show Gist options
  • Save Sgeo/3d7f8449ea5ba136038a9c677e744004 to your computer and use it in GitHub Desktop.
Save Sgeo/3d7f8449ea5ba136038a9c677e744004 to your computer and use it in GitHub Desktop.
#![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