use core::marker::PhantomData;
use crate::runtime::{AnyObject, ProtocolObject};
use crate::{ClassType, Message};
mod private_mutability {
pub trait Sealed {}
}
pub trait Mutability: private_mutability::Sealed + Sized {}
impl private_mutability::Sealed for Root {}
impl Mutability for Root {}
impl private_mutability::Sealed for Immutable {}
impl Mutability for Immutable {}
impl private_mutability::Sealed for Mutable {}
impl Mutability for Mutable {}
impl<MS: ?Sized> private_mutability::Sealed for ImmutableWithMutableSubclass<MS> {}
impl<MS: ?Sized> Mutability for ImmutableWithMutableSubclass<MS> {}
impl<IS: ?Sized> private_mutability::Sealed for MutableWithImmutableSuperclass<IS> {}
impl<IS: ?Sized> Mutability for MutableWithImmutableSuperclass<IS> {}
impl private_mutability::Sealed for InteriorMutable {}
impl Mutability for InteriorMutable {}
impl private_mutability::Sealed for MainThreadOnly {}
impl Mutability for MainThreadOnly {}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
enum Never {}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Root {
inner: Never,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Immutable {
inner: Never,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Mutable {
inner: Never,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct ImmutableWithMutableSubclass<MS: ?Sized> {
inner: Never,
mutable_subclass: PhantomData<MS>,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct MutableWithImmutableSuperclass<IS: ?Sized> {
inner: Never,
immutable_superclass: PhantomData<IS>,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct InteriorMutable {
inner: Never,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct MainThreadOnly {
inner: Never,
}
mod private_traits {
pub trait Sealed {}
}
impl<T: ?Sized + ClassType> private_traits::Sealed for T {}
impl<P: ?Sized> private_traits::Sealed for ProtocolObject<P> {}
impl private_traits::Sealed for AnyObject {}
pub unsafe trait IsIdCloneable: private_traits::Sealed {}
trait MutabilityIsIdCloneable: Mutability {}
impl MutabilityIsIdCloneable for Root {}
impl MutabilityIsIdCloneable for Immutable {}
impl<MS: ?Sized> MutabilityIsIdCloneable for ImmutableWithMutableSubclass<MS> {}
impl MutabilityIsIdCloneable for InteriorMutable {}
impl MutabilityIsIdCloneable for MainThreadOnly {}
unsafe impl<T: ?Sized + ClassType> IsIdCloneable for T where T::Mutability: MutabilityIsIdCloneable {}
unsafe impl<P: ?Sized + IsIdCloneable> IsIdCloneable for ProtocolObject<P> {}
unsafe impl IsIdCloneable for AnyObject {}
pub unsafe trait IsRetainable: private_traits::Sealed + IsIdCloneable {}
trait MutabilityIsRetainable: MutabilityIsIdCloneable {}
impl MutabilityIsRetainable for Immutable {}
impl MutabilityIsRetainable for InteriorMutable {}
impl MutabilityIsRetainable for MainThreadOnly {}
unsafe impl<T: ?Sized + ClassType> IsRetainable for T where T::Mutability: MutabilityIsRetainable {}
unsafe impl<P: ?Sized + IsRetainable> IsRetainable for ProtocolObject<P> {}
pub unsafe trait IsAllocableAnyThread: private_traits::Sealed {}
trait MutabilityIsAllocableAnyThread: Mutability {}
impl MutabilityIsAllocableAnyThread for Root {}
impl MutabilityIsAllocableAnyThread for Immutable {}
impl MutabilityIsAllocableAnyThread for Mutable {}
impl<MS: ?Sized> MutabilityIsAllocableAnyThread for ImmutableWithMutableSubclass<MS> {}
impl<IS: ?Sized> MutabilityIsAllocableAnyThread for MutableWithImmutableSuperclass<IS> {}
impl MutabilityIsAllocableAnyThread for InteriorMutable {}
unsafe impl<T: ?Sized + ClassType> IsAllocableAnyThread for T where
T::Mutability: MutabilityIsAllocableAnyThread
{
}
unsafe impl<P: ?Sized + IsAllocableAnyThread> IsAllocableAnyThread for ProtocolObject<P> {}
pub unsafe trait IsAllowedMutable: private_traits::Sealed {}
trait MutabilityIsAllowedMutable: Mutability {}
impl MutabilityIsAllowedMutable for Root {}
impl MutabilityIsAllowedMutable for Mutable {}
impl<MS: ?Sized> MutabilityIsAllowedMutable for ImmutableWithMutableSubclass<MS> {}
impl<IS: ?Sized> MutabilityIsAllowedMutable for MutableWithImmutableSuperclass<IS> {}
unsafe impl<T: ?Sized + ClassType> IsAllowedMutable for T where
T::Mutability: MutabilityIsAllowedMutable
{
}
unsafe impl<P: ?Sized + IsAllowedMutable> IsAllowedMutable for ProtocolObject<P> {}
unsafe impl IsAllowedMutable for AnyObject {}
pub unsafe trait IsMutable: private_traits::Sealed + IsAllowedMutable {}
trait MutabilityIsMutable: MutabilityIsAllowedMutable {}
impl MutabilityIsMutable for Mutable {}
impl<IS: ?Sized> MutabilityIsMutable for MutableWithImmutableSuperclass<IS> {}
unsafe impl<T: ?Sized + ClassType> IsMutable for T where T::Mutability: MutabilityIsMutable {}
unsafe impl<P: ?Sized + IsMutable> IsMutable for ProtocolObject<P> {}
pub unsafe trait IsMainThreadOnly: private_traits::Sealed {}
trait MutabilityIsMainThreadOnly: Mutability {}
impl MutabilityIsMainThreadOnly for MainThreadOnly {}
unsafe impl<T: ?Sized + ClassType> IsMainThreadOnly for T where
T::Mutability: MutabilityIsMainThreadOnly
{
}
unsafe impl<P: ?Sized + IsMainThreadOnly> IsMainThreadOnly for ProtocolObject<P> {}
pub unsafe trait HasStableHash: private_traits::Sealed {}
trait MutabilityHashIsStable: Mutability {}
impl MutabilityHashIsStable for Immutable {}
impl MutabilityHashIsStable for Mutable {}
impl<MS: ?Sized> MutabilityHashIsStable for ImmutableWithMutableSubclass<MS> {}
impl<IS: ?Sized> MutabilityHashIsStable for MutableWithImmutableSuperclass<IS> {}
unsafe impl<T: ?Sized + ClassType> HasStableHash for T where T::Mutability: MutabilityHashIsStable {}
unsafe impl<P: ?Sized + HasStableHash> HasStableHash for ProtocolObject<P> {}
pub unsafe trait CounterpartOrSelf: private_traits::Sealed {
type Immutable: ?Sized + Message;
type Mutable: ?Sized + Message;
}
mod private_counterpart {
use super::*;
pub trait MutabilityCounterpartOrSelf<T: ?Sized>: Mutability {
type Immutable: ?Sized + Message;
type Mutable: ?Sized + Message;
}
impl<T: ClassType<Mutability = Root>> MutabilityCounterpartOrSelf<T> for Root {
type Immutable = T;
type Mutable = T;
}
impl<T: ClassType<Mutability = Immutable>> MutabilityCounterpartOrSelf<T> for Immutable {
type Immutable = T;
type Mutable = T;
}
impl<T: ClassType<Mutability = Mutable>> MutabilityCounterpartOrSelf<T> for Mutable {
type Immutable = T;
type Mutable = T;
}
impl<T, MS> MutabilityCounterpartOrSelf<T> for ImmutableWithMutableSubclass<MS>
where
T: ClassType<Mutability = ImmutableWithMutableSubclass<MS>>,
MS: ClassType<Mutability = MutableWithImmutableSuperclass<T>>,
{
type Immutable = T;
type Mutable = MS;
}
impl<T, IS> MutabilityCounterpartOrSelf<T> for MutableWithImmutableSuperclass<IS>
where
T: ClassType<Mutability = MutableWithImmutableSuperclass<IS>>,
IS: ClassType<Mutability = ImmutableWithMutableSubclass<T>>,
{
type Immutable = IS;
type Mutable = T;
}
impl<T: ClassType<Mutability = InteriorMutable>> MutabilityCounterpartOrSelf<T>
for InteriorMutable
{
type Immutable = T;
type Mutable = T;
}
impl<T: ClassType<Mutability = MainThreadOnly>> MutabilityCounterpartOrSelf<T> for MainThreadOnly {
type Immutable = T;
type Mutable = T;
}
}
unsafe impl<T: ?Sized + ClassType> CounterpartOrSelf for T
where
T::Mutability: private_counterpart::MutabilityCounterpartOrSelf<T>,
{
type Immutable =
<T::Mutability as private_counterpart::MutabilityCounterpartOrSelf<T>>::Immutable;
type Mutable = <T::Mutability as private_counterpart::MutabilityCounterpartOrSelf<T>>::Mutable;
}
unsafe impl<P: ?Sized> CounterpartOrSelf for ProtocolObject<P> {
type Immutable = Self;
type Mutable = Self;
}
#[cfg(test)]
mod tests {
use crate::runtime::NSObject;
use super::*;
use core::any::TypeId;
use core::fmt;
use core::hash;
#[test]
fn generic_traits() {
fn assert_traits<T>()
where
T: Sync + Send,
T: Clone + Copy + PartialEq + Eq + PartialOrd + Ord + hash::Hash + fmt::Debug,
{
}
assert_traits::<Root>();
assert_traits::<Immutable>();
assert_traits::<Mutable>();
assert_traits::<ImmutableWithMutableSubclass<()>>();
assert_traits::<MutableWithImmutableSuperclass<()>>();
assert_traits::<InteriorMutable>();
assert_traits::<MainThreadOnly>();
#[allow(unused)]
fn test_mutability_implies_sized<M: ?Sized + Mutability>() {
fn assert_sized<T: Sized>() {}
assert_sized::<M>();
}
}
#[test]
fn counterpart_root() {
assert_eq!(
TypeId::of::<NSObject>(),
TypeId::of::<<NSObject as CounterpartOrSelf>::Immutable>(),
);
assert_eq!(
TypeId::of::<NSObject>(),
TypeId::of::<<NSObject as CounterpartOrSelf>::Mutable>(),
);
}
#[allow(unused, clippy::too_many_arguments)]
fn object_safe(
_: &dyn IsIdCloneable,
_: &dyn IsRetainable,
_: &dyn IsAllocableAnyThread,
_: &dyn IsAllowedMutable,
_: &dyn IsMutable,
_: &dyn IsMainThreadOnly,
_: &dyn HasStableHash,
_: &dyn CounterpartOrSelf<Immutable = (), Mutable = ()>,
) {
}
}