use alloc::{boxed::Box, vec::Vec};
use core::{
cell::RefCell,
num::{
NonZeroI128,
NonZeroI16,
NonZeroI32,
NonZeroI64,
NonZeroI8,
NonZeroIsize,
NonZeroU128,
NonZeroU16,
NonZeroU32,
NonZeroU64,
NonZeroU8,
NonZeroUsize,
},
};
use crate::Trace;
macro_rules! impl_empty_trace {
($($t:ty),* $(,)*) => {
$(
unsafe impl Trace for $t {
$crate::unsafe_empty_trace!{}
}
)*
};
}
impl_empty_trace! {
i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize, f32, f64,
bool, (), NonZeroI8, NonZeroU8, NonZeroI16, NonZeroU16, NonZeroI32,
NonZeroU32, NonZeroI64, NonZeroU64, NonZeroI128, NonZeroU128, NonZeroIsize,
NonZeroUsize,
}
macro_rules! impl_tuple_trace {
($(($($t:ident),*),)*) => {
$(
#[allow(non_snake_case)]
unsafe impl<$($t: Trace),*> Trace for ($($t,)*) {
unsafe fn untrace(&self) {
match *self {
($(ref $t,)*) => {
$(
unsafe { $t.untrace() };
)*
}
}
}
unsafe fn trace(&self) {
match *self {
($(ref $t,)*) => {
$(
unsafe { $t.trace() };
)*
}
}
}
unsafe fn set_undone(&self) {
match *self {
($(ref $t,)*) => {
$(
unsafe { $t.set_undone() };
)*
}
}
}
fn counts_match(&self) -> bool {
match *self {
($(ref $t,)*) => {
true $(& $t.counts_match())*
}
}
}
fn could_contain_cycles() -> bool {
false $(|| <$t>::could_contain_cycles())*
}
}
)*
}
}
impl_tuple_trace! {
(A),
(A, B),
(A, B, C),
(A, B, C, D),
(A, B, C, D, E),
(A, B, C, D, E, F),
(A, B, C, D, E, F, G),
(A, B, C, D, E, F, G, H),
(A, B, C, D, E, F, G, H, I),
(A, B, C, D, E, F, G, H, I, J),
(A, B, C, D, E, F, G, H, I, J, K),
(A, B, C, D, E, F, G, H, I, J, K, L), }
macro_rules! impl_deref_trace {
($t:ty) => {
unsafe fn untrace(&self) {
unsafe { (**self).untrace() };
}
unsafe fn trace(&self) {
unsafe { (**self).trace() };
}
unsafe fn set_undone(&self) {
unsafe { (**self).set_undone() };
}
fn counts_match(&self) -> bool {
(**self).counts_match()
}
fn could_contain_cycles() -> bool {
T::could_contain_cycles()
}
};
}
unsafe impl<T: Trace> Trace for Option<T> {
unsafe fn untrace(&self) {
if let Some(v) = self {
unsafe { v.untrace() };
}
}
unsafe fn trace(&self) {
if let Some(v) = self {
unsafe { v.trace() };
}
}
unsafe fn set_undone(&self) {
if let Some(v) = self {
unsafe { v.set_undone() };
}
}
fn counts_match(&self) -> bool {
if let Some(v) = self {
v.counts_match()
} else {
true
}
}
fn could_contain_cycles() -> bool {
T::could_contain_cycles()
}
}
unsafe impl<T: Trace + ?Sized> Trace for &'_ T {
impl_deref_trace! { T }
}
unsafe impl<T: Trace + ?Sized> Trace for &'_ mut T {
impl_deref_trace! { T }
}
unsafe impl<T: Trace + ?Sized> Trace for Box<T> {
impl_deref_trace! { T }
}
unsafe impl<T: Trace> Trace for Vec<T> {
impl_deref_trace! { [T] }
}
unsafe impl<T: Trace> Trace for [T] {
unsafe fn untrace(&self) {
for v in self {
unsafe { v.untrace() };
}
}
unsafe fn trace(&self) {
for v in self {
unsafe { v.trace() };
}
}
unsafe fn set_undone(&self) {
for v in self {
unsafe { v.set_undone() };
}
}
fn counts_match(&self) -> bool {
self.iter().all(Trace::counts_match)
}
fn could_contain_cycles() -> bool {
T::could_contain_cycles()
}
}
unsafe impl<T: Trace> Trace for RefCell<T> {
unsafe fn untrace(&self) {
if let Ok(v) = self.try_borrow() {
unsafe { v.untrace() };
}
}
unsafe fn trace(&self) {
if let Ok(v) = self.try_borrow() {
unsafe { v.trace() };
}
}
unsafe fn set_undone(&self) {
if let Ok(v) = self.try_borrow() {
unsafe { v.set_undone() };
}
}
fn counts_match(&self) -> bool {
if let Ok(v) = self.try_borrow() {
v.counts_match()
} else {
true
}
}
fn could_contain_cycles() -> bool {
T::could_contain_cycles()
}
}