use alloc::boxed::Box;
use alloc::collections::VecDeque;
use alloc::collections::{BTreeMap, BTreeSet};
use alloc::rc::Rc;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::cell::{Cell, RefCell};
#[cfg(feature = "std")]
use core::hash::BuildHasher;
use core::marker::PhantomData;
#[cfg(feature = "std")]
use std::collections::{HashMap, HashSet};
use crate::collect::Collect;
use crate::context::Collection;
#[macro_export]
macro_rules! unsafe_empty_collect {
($type:ty) => {
unsafe impl Collect for $type {
#[inline]
fn needs_trace() -> bool {
false
}
}
};
}
#[macro_export]
macro_rules! static_collect {
($type:ty) => {
unsafe impl Collect for $type
where
$type: 'static,
{
#[inline]
fn needs_trace() -> bool {
false
}
}
};
}
static_collect!(bool);
static_collect!(char);
static_collect!(u8);
static_collect!(u16);
static_collect!(u32);
static_collect!(u64);
static_collect!(usize);
static_collect!(i8);
static_collect!(i16);
static_collect!(i32);
static_collect!(i64);
static_collect!(isize);
static_collect!(f32);
static_collect!(f64);
static_collect!(String);
static_collect!(str);
static_collect!(alloc::ffi::CString);
static_collect!(core::ffi::CStr);
static_collect!(core::any::TypeId);
#[cfg(feature = "std")]
static_collect!(std::path::Path);
#[cfg(feature = "std")]
static_collect!(std::path::PathBuf);
#[cfg(feature = "std")]
static_collect!(std::ffi::OsStr);
#[cfg(feature = "std")]
static_collect!(std::ffi::OsString);
unsafe impl<T: ?Sized + 'static> Collect for &'static T {
#[inline]
fn needs_trace() -> bool {
false
}
}
unsafe impl<T: ?Sized + Collect> Collect for Box<T> {
#[inline]
fn trace(&self, cc: &Collection) {
(**self).trace(cc)
}
}
unsafe impl<T: Collect> Collect for [T] {
#[inline]
fn needs_trace() -> bool {
T::needs_trace()
}
#[inline]
fn trace(&self, cc: &Collection) {
for t in self.iter() {
t.trace(cc)
}
}
}
unsafe impl<T: Collect> Collect for Option<T> {
#[inline]
fn needs_trace() -> bool {
T::needs_trace()
}
#[inline]
fn trace(&self, cc: &Collection) {
if let Some(t) = self.as_ref() {
t.trace(cc)
}
}
}
unsafe impl<T: Collect, E: Collect> Collect for Result<T, E> {
#[inline]
fn needs_trace() -> bool {
T::needs_trace() || E::needs_trace()
}
#[inline]
fn trace(&self, cc: &Collection) {
match self {
Ok(r) => r.trace(cc),
Err(e) => e.trace(cc),
}
}
}
unsafe impl<T: Collect> Collect for Vec<T> {
#[inline]
fn needs_trace() -> bool {
T::needs_trace()
}
#[inline]
fn trace(&self, cc: &Collection) {
for t in self {
t.trace(cc)
}
}
}
unsafe impl<T: Collect> Collect for VecDeque<T> {
#[inline]
fn needs_trace() -> bool {
T::needs_trace()
}
#[inline]
fn trace(&self, cc: &Collection) {
for t in self {
t.trace(cc)
}
}
}
#[cfg(feature = "std")]
unsafe impl<K, V, S> Collect for HashMap<K, V, S>
where
K: Collect,
V: Collect,
S: BuildHasher + 'static,
{
#[inline]
fn needs_trace() -> bool {
K::needs_trace() || V::needs_trace()
}
#[inline]
fn trace(&self, cc: &Collection) {
for (k, v) in self {
k.trace(cc);
v.trace(cc);
}
}
}
#[cfg(feature = "std")]
unsafe impl<T, S> Collect for HashSet<T, S>
where
T: Collect,
S: BuildHasher + 'static,
{
#[inline]
fn needs_trace() -> bool {
T::needs_trace()
}
#[inline]
fn trace(&self, cc: &Collection) {
for v in self {
v.trace(cc);
}
}
}
unsafe impl<K, V> Collect for BTreeMap<K, V>
where
K: Collect,
V: Collect,
{
#[inline]
fn needs_trace() -> bool {
K::needs_trace() || V::needs_trace()
}
#[inline]
fn trace(&self, cc: &Collection) {
for (k, v) in self {
k.trace(cc);
v.trace(cc);
}
}
}
unsafe impl<T> Collect for BTreeSet<T>
where
T: Collect,
{
#[inline]
fn needs_trace() -> bool {
T::needs_trace()
}
#[inline]
fn trace(&self, cc: &Collection) {
for v in self {
v.trace(cc);
}
}
}
unsafe impl<T> Collect for Rc<T>
where
T: ?Sized + Collect,
{
#[inline]
fn trace(&self, cc: &Collection) {
(**self).trace(cc);
}
}
unsafe impl<T> Collect for Arc<T>
where
T: ?Sized + Collect,
{
#[inline]
fn trace(&self, cc: &Collection) {
(**self).trace(cc);
}
}
unsafe impl<T> Collect for Cell<T>
where
T: 'static,
{
#[inline]
fn needs_trace() -> bool {
false
}
}
unsafe impl<T> Collect for RefCell<T>
where
T: 'static,
{
#[inline]
fn needs_trace() -> bool {
false
}
}
unsafe impl<T> Collect for PhantomData<T> {
#[inline]
fn needs_trace() -> bool {
false
}
}
unsafe impl<T: Collect, const N: usize> Collect for [T; N] {
#[inline]
fn needs_trace() -> bool {
T::needs_trace()
}
#[inline]
fn trace(&self, cc: &Collection) {
for t in self {
t.trace(cc)
}
}
}
macro_rules! impl_tuple {
() => (
unsafe impl Collect for () {
#[inline]
fn needs_trace() -> bool {
false
}
}
);
($($name:ident)+) => (
unsafe impl<$($name,)*> Collect for ($($name,)*)
where $($name: Collect,)*
{
#[inline]
fn needs_trace() -> bool {
$($name::needs_trace() ||)* false
}
#[allow(non_snake_case)]
#[inline]
fn trace(&self, cc: &Collection) {
let ($($name,)*) = self;
$($name.trace(cc);)*
}
}
);
}
impl_tuple! {}
impl_tuple! {A}
impl_tuple! {A B}
impl_tuple! {A B C}
impl_tuple! {A B C D}
impl_tuple! {A B C D E}
impl_tuple! {A B C D E F}
impl_tuple! {A B C D E F G}
impl_tuple! {A B C D E F G H}
impl_tuple! {A B C D E F G H I}
impl_tuple! {A B C D E F G H I J}
impl_tuple! {A B C D E F G H I J K}
impl_tuple! {A B C D E F G H I J K L}
impl_tuple! {A B C D E F G H I J K L M}
impl_tuple! {A B C D E F G H I J K L M N}
impl_tuple! {A B C D E F G H I J K L M N O}
impl_tuple! {A B C D E F G H I J K L M N O P}