use crate::utils::aliasable_box::AliasableBox;
use crate::utils::aliasable_box::AliasableBoxExt;
use std::cell::Cell;
use std::rc::Rc;
struct Payload {
value: u64,
drops: Rc<Cell<usize>>,
}
impl Drop for Payload {
fn drop(&mut self) {
self.drops.set(self.drops.get() + 1);
}
}
fn payload(value: u64) -> (AliasableBox<Payload>, Rc<Cell<usize>>) {
let drops = Rc::new(Cell::new(0));
let payload = Payload {
value,
drops: drops.clone(),
};
(Box::new(payload).into_aliasable(), drops)
}
#[test]
fn deref() {
let (mut b, _drops) = payload(1);
assert_eq!(b.value, 1);
b.value = 2;
assert_eq!(b.value, 2);
}
#[test]
fn drop_runs_once() {
let (b, drops) = payload(1);
assert_eq!(drops.get(), 0);
drop(b);
assert_eq!(drops.get(), 1);
}
#[test]
fn into_box() {
let (b, drops) = payload(1);
let addr = &*b as *const Payload;
let b = b.into_box();
assert_eq!(&*b as *const Payload, addr);
assert_eq!(b.value, 1);
assert_eq!(drops.get(), 0);
drop(b);
assert_eq!(drops.get(), 1);
}
#[test]
fn stable_address() {
struct Holder {
ptr: *const u64,
b: AliasableBox<Payload>,
}
#[inline(never)]
fn take(h: Box<Holder>) -> Box<Holder> {
h
}
let (b, drops) = payload(7);
let ptr: *const u64 = &b.value;
let h = take(Box::new(Holder { ptr, b }));
let mut v = vec![h];
let h = v.pop().unwrap();
assert_eq!(unsafe { *h.ptr }, 7);
assert_eq!(h.ptr, &h.b.value as *const u64);
assert_eq!(drops.get(), 0);
drop(h);
assert_eq!(drops.get(), 1);
}
#[test]
fn unsized_payload() {
trait Value {
fn value(&self) -> u64;
}
impl Value for Payload {
fn value(&self) -> u64 {
self.value
}
}
let drops = Rc::new(Cell::new(0));
let payload = Payload {
value: 9,
drops: drops.clone(),
};
let b: Box<dyn Value> = Box::new(payload);
let b = b.into_aliasable();
assert_eq!(b.value(), 9);
let b = b.into_box();
assert_eq!(b.value(), 9);
drop(b);
assert_eq!(drops.get(), 1);
}
#[test]
fn clone() {
let a = Box::new(5u64).into_aliasable();
let b = a.clone();
assert_eq!(*b, 5);
assert_ne!(&*a as *const u64, &*b as *const u64);
}
#[test]
fn clone_from() {
let mut a = Box::new(1u64).into_aliasable();
let b = Box::new(2u64).into_aliasable();
let addr = &*a as *const u64;
a.clone_from(&b);
assert_eq!(*a, 2);
assert_eq!(&*a as *const u64, addr);
}
#[test]
fn default_and_debug() {
let a = AliasableBox::<u64>::default();
assert_eq!(*a, 0);
assert_eq!(format!("{a:?}"), "0");
}