use crate::report::TypeReport;
use self::unsigned::{Alignment, IUnsignedBase};
use super::typenum2::*;
use super::unsigned::{IBitBase, NonZero};
use super::{FieldPair, Struct, Union};
use stabby_macros::tyeval;
macro_rules! same_as {
($t: ty) => {
type Align = <$t as IStable>::Align;
type Size = <$t as IStable>::Size;
type UnusedBits = <$t as IStable>::UnusedBits;
type ForbiddenValues = <$t as IStable>::ForbiddenValues;
type HasExactlyOneNiche = <$t as IStable>::HasExactlyOneNiche;
type ContainsIndirections = <$t as IStable>::ContainsIndirections;
const REPORT: &'static TypeReport = <$t as IStable>::REPORT;
const ID: u64 = <$t as IStable>::ID;
};
}
pub unsafe trait IStable: Sized {
type Size: Unsigned;
type Align: Alignment;
type ForbiddenValues: IForbiddenValues;
type UnusedBits: IBitMask;
type HasExactlyOneNiche: ISaturatingAdd;
type ContainsIndirections: Bit;
const REPORT: &'static TypeReport;
const ID: u64;
fn size() -> usize {
let size = Self::Size::USIZE;
let align = Self::Align::USIZE;
size + ((align - (size % align)) % align)
}
fn align() -> usize {
Self::Align::USIZE
}
}
pub unsafe trait IPod: Copy {
fn identifier() -> u64;
}
unsafe impl<T: IStable<ContainsIndirections = B0> + Copy> IPod for T {
fn identifier() -> u64 {
T::ID
}
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NotPod<T>(pub T);
impl<T> core::ops::Deref for NotPod<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> core::ops::DerefMut for NotPod<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
unsafe impl<T: IStable> IStable for NotPod<T> {
type Size = T::Size;
type Align = T::Align;
type ContainsIndirections = B1;
type ForbiddenValues = T::ForbiddenValues;
type HasExactlyOneNiche = T::HasExactlyOneNiche;
type UnusedBits = T::UnusedBits;
primitive_report!("NotPod", T);
}
#[repr(transparent)]
pub struct NicheExporter<
ForbiddenValues: IForbiddenValues,
UnusedBits: IBitMask,
HasExactlyOneNiche: ISaturatingAdd,
>(core::marker::PhantomData<(ForbiddenValues, UnusedBits, HasExactlyOneNiche)>);
impl<
ForbiddenValues: IForbiddenValues,
UnusedBits: IBitMask,
HasExactlyOneNiche: ISaturatingAdd,
> Unpin for NicheExporter<ForbiddenValues, UnusedBits, HasExactlyOneNiche>
{
}
impl<
ForbiddenValues: IForbiddenValues,
UnusedBits: IBitMask,
HasExactlyOneNiche: ISaturatingAdd,
> Clone for NicheExporter<ForbiddenValues, UnusedBits, HasExactlyOneNiche>
{
fn clone(&self) -> Self {
*self
}
}
impl<
ForbiddenValues: IForbiddenValues,
UnusedBits: IBitMask,
HasExactlyOneNiche: ISaturatingAdd,
> Copy for NicheExporter<ForbiddenValues, UnusedBits, HasExactlyOneNiche>
{
}
impl<
ForbiddenValues: IForbiddenValues,
UnusedBits: IBitMask,
HasExactlyOneNiche: ISaturatingAdd,
> Default for NicheExporter<ForbiddenValues, UnusedBits, HasExactlyOneNiche>
{
fn default() -> Self {
Self(core::marker::PhantomData)
}
}
unsafe impl<
ForbiddenValues: IForbiddenValues,
UnusedBits: IBitMask,
HasExactlyOneNiche: ISaturatingAdd,
> IStable for NicheExporter<ForbiddenValues, UnusedBits, HasExactlyOneNiche>
{
type Size = U0;
type Align = U1;
type ForbiddenValues = ForbiddenValues;
type UnusedBits = UnusedBits;
type HasExactlyOneNiche = HasExactlyOneNiche;
type ContainsIndirections = B0;
primitive_report!("NicheExporter");
}
#[crate::stabby]
#[derive(Default, Debug, Clone, Copy)]
pub struct End;
pub struct Array<Offset: Unsigned, T, Rest>(core::marker::PhantomData<(Offset, T, Rest)>);
impl<Offset: Unsigned, T, Rest> Default for Array<Offset, T, Rest> {
fn default() -> Self {
Self(Default::default())
}
}
pub trait IBitMask {
const TUPLE: Self::Tuple;
type Tuple: core::fmt::Debug;
type ByteAt<O: Unsigned>: Unsigned;
type BitOr<T: IBitMask>: IBitMask;
type Shift<O: Unsigned>: IBitMask;
type BitAnd<T: IBitMask>: IBitMask;
type HasFreeByteAt<O: Unsigned>: Bit;
type ExtractBit: IBitMask;
type ExtractedBitByteOffset: Unsigned;
type ExtractedBitMask: Unsigned;
}
impl IBitMask for End {
const TUPLE: Self::Tuple = ();
type Tuple = ();
type ByteAt<O: Unsigned> = U0;
type BitOr<T: IBitMask> = T;
type Shift<O: Unsigned> = End;
type BitAnd<T: IBitMask> = End;
type HasFreeByteAt<O: Unsigned> = B0;
type ExtractBit = End;
type ExtractedBitMask = Saturator;
type ExtractedBitByteOffset = Saturator;
}
impl<Offset: Unsigned, T: NonZero, Rest: IBitMask> IBitMask for Array<Offset, T, Rest> {
const TUPLE: Self::Tuple = ((Offset::USIZE, T::USIZE), Rest::TUPLE);
type Tuple = ((usize, usize), Rest::Tuple);
type ByteAt<O: Unsigned> = <Offset::Equal<O> as Bit>::UTernary<T, Rest::ByteAt<O>>;
type BitAnd<Mask: IBitMask> =
<<T::BitAnd<Mask::ByteAt<Offset>> as Unsigned>::Equal<U0> as Bit>::BmTernary<
Rest::BitAnd<Mask>,
Array<
Offset,
<T::BitAnd<Mask::ByteAt<Offset>> as Unsigned>::NonZero,
Rest::BitAnd<Mask>,
>,
>;
type BitOr<Arr: IBitMask> = Array<Offset, T, Rest::BitOr<Arr>>;
type Shift<O: Unsigned> = Array<Offset::Add<O>, T, Rest::Shift<O>>;
type HasFreeByteAt<O: Unsigned> =
<<O::Equal<Offset> as Bit>::And<T::Equal<UxFF>> as Bit>::Or<Rest::HasFreeByteAt<O>>;
type ExtractBit =
<<T::AbsSub<T::TruncateAtRightmostOne> as Unsigned>::Greater<U0> as Bit>::BmTernary<
Array<Offset, <T::AbsSub<T::TruncateAtRightmostOne> as Unsigned>::NonZero, Rest>,
Rest,
>;
type ExtractedBitByteOffset = Offset;
type ExtractedBitMask = T::TruncateAtRightmostOne;
}
pub trait IForbiddenValues {
type Shift<O: Unsigned>: IForbiddenValues;
type Or<T: IForbiddenValues>: IForbiddenValues;
type SelectFrom<Mask: IBitMask>: ISingleForbiddenValue;
type SelectOne: ISingleForbiddenValue;
}
pub trait ISingleForbiddenValue {
type Push<O: Unsigned, T>: ISingleForbiddenValue;
type Or<T: ISingleForbiddenValue>: ISingleForbiddenValue;
type And<T: ISingleForbiddenValue>: ISingleForbiddenValue;
type Resolve: ISingleForbiddenValue;
}
impl IForbiddenValues for End {
type Shift<O: Unsigned> = End;
type Or<T: IForbiddenValues> = T;
type SelectFrom<Mask: IBitMask> = End;
type SelectOne = End;
}
impl ISingleForbiddenValue for Saturator {
type Push<O: Unsigned, T> = Saturator;
type Or<T: ISingleForbiddenValue> = T;
type And<T: ISingleForbiddenValue> = Saturator;
type Resolve = End;
}
impl ISingleForbiddenValue for End {
type Push<O: Unsigned, T> = Array<O, T, Self>;
type Or<T: ISingleForbiddenValue> = T;
type And<T: ISingleForbiddenValue> = T;
type Resolve = Self;
}
impl<Offset: Unsigned, T, Rest: ISingleForbiddenValue> ISingleForbiddenValue
for Array<Offset, T, Rest>
{
type Push<O: Unsigned, V> = Array<O, V, Self>;
type Or<V: ISingleForbiddenValue> = Self;
type And<V: ISingleForbiddenValue> = V;
type Resolve = Self;
}
impl<Offset: Unsigned, T, Rest: IForbiddenValues> IForbiddenValues for Array<Offset, T, Rest> {
type Shift<O: Unsigned> = Array<Offset::Add<O>, T, Rest::Shift<O>>;
type Or<O: IForbiddenValues> = Or<O, Self>;
type SelectFrom<Mask: IBitMask> =
<<Mask::HasFreeByteAt<Offset> as IBitBase>::AsForbiddenValue as ISingleForbiddenValue>::And<
<Rest::SelectFrom<Mask> as ISingleForbiddenValue>::Push<Offset, T>,
>;
type SelectOne = Array<Offset, T, Rest::SelectOne>;
}
impl<A: IForbiddenValues, B: IForbiddenValues> IForbiddenValues for Or<A, B> {
type Shift<O: Unsigned> = Or<A::Shift<O>, B::Shift<O>>;
type Or<T: IForbiddenValues> = Or<T, Self>;
type SelectFrom<Mask: IBitMask> =
<A::SelectFrom<Mask> as ISingleForbiddenValue>::Or<B::SelectFrom<Mask>>;
type SelectOne = A::SelectOne;
}
pub struct Or<A, B>(core::marker::PhantomData<(A, B)>);
pub trait IsEnd {
type Output: Bit;
}
impl IsEnd for End {
type Output = B1;
}
impl<O: Unsigned, T, R: IBitMask> IsEnd for Array<O, T, R> {
type Output = B0;
}
unsafe impl<A: IStable, B: IStable> IStable for FieldPair<A, B> {
type ForbiddenValues =
Or<A::ForbiddenValues, <AlignedAfter<B, A::Size> as IStable>::ForbiddenValues>;
type UnusedBits =
<A::UnusedBits as IBitMask>::BitOr<<AlignedAfter<B, A::Size> as IStable>::UnusedBits>;
type Size = <AlignedAfter<B, A::Size> as IStable>::Size;
type Align = <A::Align as Alignment>::Max<B::Align>;
type HasExactlyOneNiche = <A::HasExactlyOneNiche as ISaturatingAdd>::SaturatingAdd<
<AlignedAfter<B, A::Size> as IStable>::HasExactlyOneNiche,
>;
type ContainsIndirections = <A::ContainsIndirections as Bit>::Or<B::ContainsIndirections>;
primitive_report!("FP");
}
pub enum SaturatingAddValue {
B0,
B1,
Saturator,
}
pub trait ISaturatingAdd {
const VALUE: SaturatingAddValue;
type SaturatingAddB1: ISaturatingAdd;
type SaturatingAdd<B: ISaturatingAdd>: ISaturatingAdd;
}
impl ISaturatingAdd for B0 {
const VALUE: SaturatingAddValue = SaturatingAddValue::B0;
type SaturatingAdd<B: ISaturatingAdd> = B;
type SaturatingAddB1 = B1;
}
impl ISaturatingAdd for B1 {
const VALUE: SaturatingAddValue = SaturatingAddValue::B1;
type SaturatingAddB1 = Saturator;
type SaturatingAdd<B: ISaturatingAdd> = B::SaturatingAddB1;
}
impl ISaturatingAdd for Saturator {
const VALUE: SaturatingAddValue = SaturatingAddValue::Saturator;
type SaturatingAddB1 = Saturator;
type SaturatingAdd<B: ISaturatingAdd> = Saturator;
}
pub struct Saturator;
pub trait Includes<SubSet> {
type Output;
}
impl<T> Includes<End> for T {
type Output = End;
}
impl<O: Unsigned, T, R: IBitMask> Includes<Array<O, T, R>> for End {
type Output = End;
}
impl<O1: Unsigned, T1, R1: IBitMask, O2: Unsigned, T2, R2: IBitMask> Includes<Array<O1, T1, R1>>
for Array<O2, T2, R2>
where
Array<O2, T2, R2>: IncludesComputer<(O1, T1)> + Includes<R1>,
R1: IsEnd,
<Self as Includes<R1>>::Output: IsEnd,
(
<Self as IncludesComputer<(O1, T1)>>::Output,
<Self as Includes<R1>>::Output,
<<Self as Includes<R1>>::Output as IsEnd>::Output,
<R1 as IsEnd>::Output,
): Arrayify,
{
type Output = <(
<Self as IncludesComputer<(O1, T1)>>::Output,
<Self as Includes<R1>>::Output,
<<Self as Includes<R1>>::Output as IsEnd>::Output,
<R1 as IsEnd>::Output,
) as Arrayify>::Output;
}
impl<O1: Unsigned, T1> Arrayify for ((O1, T1), End, B1, B1) {
type Output = Array<O1, T1, End>;
}
impl<O1: Unsigned, T1> Arrayify for ((O1, T1), End, B1, B0) {
type Output = End;
}
impl<O1: Unsigned, T1, Tail: IBitMask> Arrayify for ((O1, T1), Tail, B0, B0) {
type Output = Array<O1, T1, Tail>;
}
impl<Tail, T, U> Arrayify for (End, Tail, T, U) {
type Output = End;
}
pub trait Arrayify {
type Output;
}
pub trait IncludesComputer<SubSet> {
type Output;
}
impl<O1: Unsigned, T1, O2: Unsigned, T2, R2: IBitMask> IncludesComputer<(O1, T1)>
for Array<O2, T2, R2>
where
Self: IncludesComputer<(O1, T1, tyeval!(O1 == O2))>,
{
type Output = <Self as IncludesComputer<(O1, T1, tyeval!(O1 == O2))>>::Output;
}
impl<O1: Unsigned, T1, O2: Unsigned, T2, R2: IBitMask> IncludesComputer<(O1, T1, B0)>
for Array<O2, T2, R2>
where
R2: IncludesComputer<(O1, T1)>,
{
type Output = <R2 as IncludesComputer<(O1, T1)>>::Output;
}
impl<O1: Unsigned, T1, O2: Unsigned, T2: Unsigned, R2: IBitMask> IncludesComputer<(O1, T1, B1)>
for Array<O2, T2, R2>
where
Self: IncludesComputer<(O1, T1, B1, tyeval!(T2 == U255))>,
{
type Output = <Self as IncludesComputer<(O1, T1, B1, tyeval!(T2 == U255))>>::Output;
}
impl<O1: Unsigned, T1, O2: Unsigned, T2, R2: IBitMask> IncludesComputer<(O1, T1, B1, B1)>
for Array<O2, T2, R2>
{
type Output = (O1, T1);
}
impl<O1: Unsigned, T1, O2: Unsigned, T2, R2: IBitMask> IncludesComputer<(O1, T1, B1, B0)>
for Array<O2, T2, R2>
{
type Output = End;
}
unsafe impl<A: IStable, B: IStable> IStable for Union<A, B>
where
(Self, tyeval!(A::Align == B::Align)): IStable,
{
same_as!((Self, tyeval!(A::Align == B::Align)));
}
unsafe impl<A: IStable, B: IStable> IStable for (Union<A, B>, B1) {
type ForbiddenValues = End;
type UnusedBits = End;
type Size = <A::Size as Unsigned>::Max<B::Size>;
type Align = <A::Align as Alignment>::Max<B::Align>;
type HasExactlyOneNiche = B0;
type ContainsIndirections = <A::ContainsIndirections as Bit>::Or<B::ContainsIndirections>;
primitive_report!("Union");
}
unsafe impl<A: IStable, B: IStable> IStable for (Union<A, B>, B0)
where
Struct<(Union<A, B>, B1)>: IStable,
{
same_as!(Struct<(Union<A, B>, B1)>);
}
pub struct AlignedAfter<T, Start: Unsigned>(core::marker::PhantomData<(T, Start)>);
unsafe impl<T: IStable, Start: Unsigned> IStable for AlignedAfter<T, Start> {
type Align = T::Align;
type Size = <T::Size as Unsigned>::Add<Start::NextMultipleOf<T::Align>>;
type ForbiddenValues =
<T::ForbiddenValues as IForbiddenValues>::Shift<Start::NextMultipleOf<T::Align>>;
type UnusedBits = <<<tyeval!(Start::NextMultipleOf<T::Align> - Start) as IUnsignedBase>::PaddingBitMask as IBitMask>::Shift<Start> as IBitMask>::BitOr<
<T::UnusedBits as IBitMask>::Shift<Start::NextMultipleOf<T::Align>>,
>;
type HasExactlyOneNiche = T::HasExactlyOneNiche;
type ContainsIndirections = T::ContainsIndirections;
primitive_report!("FP");
}
unsafe impl<T: IStable> IStable for Struct<T> {
type Size = <T::Size as Unsigned>::NextMultipleOf<T::Align>;
type Align = T::Align;
type ForbiddenValues = T::ForbiddenValues;
type UnusedBits = <T::UnusedBits as IBitMask>::BitOr<
<<tyeval!(<T::Size as Unsigned>::NextMultipleOf<T::Align> - T::Size) as IUnsignedBase>::PaddingBitMask as IBitMask>::Shift<T::Size>>;
type HasExactlyOneNiche = Saturator;
type ContainsIndirections = T::ContainsIndirections;
primitive_report!("FP");
}