use std::mem::size_of;
use std::ptr;
use std::task::{Context, RawWaker, RawWakerVTable, Waker};
fn noop(_: *const ()) {}
fn clone_waker(p: *const ()) -> RawWaker {
RawWaker::new(p, &VTABLE)
}
static VTABLE: RawWakerVTable = RawWakerVTable::new(clone_waker, noop, noop, noop);
#[repr(C)]
struct WakerRepr {
vtable: *const (),
data: *const (),
}
fn main() {
assert!(
size_of::<Waker>() == 16,
"nexus-async-rt: Waker size is {}, expected 16. \
ReusableWaker layout assumption is broken.",
size_of::<Waker>()
);
let sentinel = 0xDEAD_BEEF_CAFE_u64 as *const ();
let raw = RawWaker::new(sentinel, &VTABLE);
let waker = std::mem::ManuallyDrop::new(unsafe { Waker::from_raw(raw) });
let repr: WakerRepr = unsafe { ptr::read(ptr::addr_of!(*waker).cast::<WakerRepr>()) };
assert!(
repr.vtable == ((&raw const VTABLE) as *const ()),
"nexus-async-rt: Waker field order is not [vtable, data]. \
Expected vtable at offset 0. This compiler is not supported."
);
assert!(
repr.data == sentinel,
"nexus-async-rt: Waker field order is not [vtable, data]. \
Expected data at offset 8. This compiler is not supported."
);
assert!(
size_of::<Context<'_>>() <= 32,
"nexus-async-rt: Context size is {}, expected <= 32. \
ReusableWaker layout assumption is broken.",
size_of::<Context<'_>>()
);
let cx = Context::from_waker(&waker);
let first_word: *const () = unsafe { ptr::read(ptr::addr_of!(cx).cast::<*const ()>()) };
assert!(
first_word == (ptr::addr_of!(*waker) as *const ()),
"nexus-async-rt: Context first field is not &Waker. \
ReusableWaker layout assumption is broken."
);
}