#![feature(ptr_internals)]

fn main() {
    into_raw();
    into_unique();
    boxed_pair_to_vec();
}

fn into_raw() {
    unsafe {
        let b = Box::new(4i32);
        let r = Box::into_raw(b);

        // "lose the tag"
        let r2 = ((r as usize) + 0) as *mut i32;
        *(&mut *r2) = 7;

        // Use original ptr again
        *(&mut *r) = 17;
        drop(Box::from_raw(r));
    }
}

fn into_unique() {
    unsafe {
        let b = Box::new(4i32);
        let u = Box::into_unique(b).0;

        // "lose the tag"
        let r = ((u.as_ptr() as usize) + 0) as *mut i32;
        *(&mut *r) = 7;

        // Use original ptr again.
        drop(Box::from_raw(u.as_ptr()));
    }
}

fn boxed_pair_to_vec() {
    #[repr(C)]
    #[derive(Debug)]
    struct PairFoo {
        fst: Foo,
        snd: Foo,
    }

    #[derive(Debug)]
    struct Foo(u64);
    fn reinterstruct(box_pair: Box<PairFoo>) -> Vec<Foo> {
        let ref_pair = Box::leak(box_pair) as *mut PairFoo;
        let ptr_foo = unsafe { std::ptr::addr_of_mut!((*ref_pair).fst) };
        unsafe { Vec::from_raw_parts(ptr_foo, 2, 2) }
    }

    let pair_foo = Box::new(PairFoo { fst: Foo(42), snd: Foo(1337) });
    println!("pair_foo = {:?}", pair_foo);
    for (n, foo) in reinterstruct(pair_foo).into_iter().enumerate() {
        println!("foo #{} = {:?}", n, foo);
    }
}