use crate::heap::Heap;
use alloc::vec::Vec;
pub trait Trace: 'static {
fn trace(&self, t: &mut Tracer<'_>);
}
pub type TraceFn = unsafe fn(*const u8, usize, &mut Tracer<'_>);
pub fn trace_fn<T: Trace>() -> TraceFn {
|p, _, t| {
let v = unsafe { &*(p as *const T) };
v.trace(t);
}
}
pub fn trace_array_fn<T: Trace>() -> TraceFn {
|p, bytes, t| {
let n = bytes / size_of::<T>();
let vs = unsafe { core::slice::from_raw_parts(p as *const T, n) };
for v in vs {
v.trace(t);
}
}
}
pub struct Tracer<'h> {
pub(crate) heap: &'h mut Heap,
pub(crate) work: Vec<usize>,
}
macro_rules! no_refs {
($($t:ty),*) => {$(
impl Trace for $t {
#[inline]
fn trace(&self, _: &mut Tracer<'_>) {}
}
)*};
}
no_refs!(bool, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, ());
impl<T: Trace, const N: usize> Trace for [T; N] {
#[inline]
fn trace(&self, t: &mut Tracer<'_>) {
for v in self {
v.trace(t);
}
}
}
macro_rules! tuple_trace {
($($t:ident $i:tt),+) => {
impl<$($t: Trace),+> Trace for ($($t,)+) {
#[inline]
fn trace(&self, t: &mut Tracer<'_>) { $(self.$i.trace(t);)+ }
}
};
}
tuple_trace!(A 0);
tuple_trace!(A 0, B 1);
tuple_trace!(A 0, B 1, C 2);
tuple_trace!(A 0, B 1, C 2, D 3);
tuple_trace!(A 0, B 1, C 2, D 3, E 4);
tuple_trace!(A 0, B 1, C 2, D 3, E 4, F 5);
tuple_trace!(A 0, B 1, C 2, D 3, E 4, F 5, G 6);
tuple_trace!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7);
tuple_trace!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8);
tuple_trace!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9);
tuple_trace!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10);
tuple_trace!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11);