1use crate::report::TypeReport;
16
17use self::unsigned::{Alignment, IUnsignedBase};
18
19use super::typenum2::*;
20use super::unsigned::{IBitBase, NonZero};
21use super::{AlignedStruct, FieldPair, Struct, Union};
22use stabby_macros::tyeval;
23
24pub unsafe trait IStable: Sized {
31 type Size: Unsigned;
33 type Align: Alignment;
35 type ForbiddenValues: IForbiddenValues;
37 type UnusedBits: IBitMask;
39 type HasExactlyOneNiche: ISaturatingAdd;
45 type ContainsIndirections: Bit;
47 #[cfg(feature = "experimental-ctypes")]
48 type CType: IStable;
50 const REPORT: &'static TypeReport;
52 const ID: u64;
54 fn size() -> usize {
56 let size = Self::Size::USIZE;
57 let align = Self::Align::USIZE;
58 size + ((align - (size % align)) % align)
59 }
60 fn align() -> usize {
62 Self::Align::USIZE
63 }
64 unsafe fn is_invalid(ptr: *const u8) -> bool {
73 Self::ForbiddenValues::is_invalid(ptr)
74 }
75}
76
77pub unsafe trait IPod: Copy {
96 fn identifier() -> u64;
98}
99unsafe impl<T: IStable<ContainsIndirections = B0> + Copy> IPod for T {
101 fn identifier() -> u64 {
102 T::ID
103 }
104}
105
106#[repr(transparent)]
108#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
109pub struct NotPod<T>(pub T);
110impl<T> core::ops::Deref for NotPod<T> {
111 type Target = T;
112 fn deref(&self) -> &Self::Target {
113 &self.0
114 }
115}
116impl<T> core::ops::DerefMut for NotPod<T> {
117 fn deref_mut(&mut self) -> &mut Self::Target {
118 &mut self.0
119 }
120}
121unsafe impl<T: IStable> IStable for NotPod<T> {
123 type Size = T::Size;
124 type Align = T::Align;
125 type ContainsIndirections = B1;
126 type ForbiddenValues = T::ForbiddenValues;
127 type HasExactlyOneNiche = T::HasExactlyOneNiche;
128 type UnusedBits = T::UnusedBits;
129 #[cfg(feature = "experimental-ctypes")]
130 type CType = T::CType;
131 primitive_report!("NotPod", T);
132}
133
134#[repr(transparent)]
142pub struct NicheExporter<
143 ForbiddenValues: IForbiddenValues,
144 UnusedBits: IBitMask,
145 HasExactlyOneNiche: ISaturatingAdd,
146>(core::marker::PhantomData<(ForbiddenValues, UnusedBits, HasExactlyOneNiche)>);
147
148impl<
149 ForbiddenValues: IForbiddenValues,
150 UnusedBits: IBitMask,
151 HasExactlyOneNiche: ISaturatingAdd,
152 > Unpin for NicheExporter<ForbiddenValues, UnusedBits, HasExactlyOneNiche>
153{
154}
155
156impl<
157 ForbiddenValues: IForbiddenValues,
158 UnusedBits: IBitMask,
159 HasExactlyOneNiche: ISaturatingAdd,
160 > Clone for NicheExporter<ForbiddenValues, UnusedBits, HasExactlyOneNiche>
161{
162 fn clone(&self) -> Self {
163 *self
164 }
165}
166impl<
167 ForbiddenValues: IForbiddenValues,
168 UnusedBits: IBitMask,
169 HasExactlyOneNiche: ISaturatingAdd,
170 > Copy for NicheExporter<ForbiddenValues, UnusedBits, HasExactlyOneNiche>
171{
172}
173impl<
174 ForbiddenValues: IForbiddenValues,
175 UnusedBits: IBitMask,
176 HasExactlyOneNiche: ISaturatingAdd,
177 > Default for NicheExporter<ForbiddenValues, UnusedBits, HasExactlyOneNiche>
178{
179 fn default() -> Self {
180 Self(core::marker::PhantomData)
181 }
182}
183unsafe impl<
185 ForbiddenValues: IForbiddenValues,
186 UnusedBits: IBitMask,
187 HasExactlyOneNiche: ISaturatingAdd,
188 > IStable for NicheExporter<ForbiddenValues, UnusedBits, HasExactlyOneNiche>
189{
190 type Size = U0;
191 type Align = U1;
192 type ForbiddenValues = ForbiddenValues;
193 type UnusedBits = UnusedBits;
194 type HasExactlyOneNiche = HasExactlyOneNiche;
195 type ContainsIndirections = B0;
196 #[cfg(feature = "experimental-ctypes")]
197 type CType = ();
198 primitive_report!("NicheExporter");
199}
200
201#[crate::stabby]
203#[derive(Default, Debug, Clone, Copy)]
204pub struct End;
205pub struct Array<Offset: Unsigned, T, Rest>(core::marker::PhantomData<(Offset, T, Rest)>);
207impl<Offset: Unsigned, T, Rest> Default for Array<Offset, T, Rest> {
208 fn default() -> Self {
209 Self(Default::default())
210 }
211}
212
213pub trait IBitMask {
215 const TUPLE: Self::Tuple;
217 type Tuple: core::fmt::Debug;
219 type ByteAt<O: Unsigned>: Unsigned;
221 type BitOr<T: IBitMask>: IBitMask;
223 type Shift<O: Unsigned>: IBitMask;
225 type BitAnd<T: IBitMask>: IBitMask;
227 type HasFreeByteAt<O: Unsigned>: Bit;
229 type ExtractBit: IBitMask;
231 type ExtractedBitByteOffset: Unsigned;
233 type ExtractedBitMask: Unsigned;
235}
236impl IBitMask for End {
237 const TUPLE: Self::Tuple = ();
238 type Tuple = ();
239 type ByteAt<O: Unsigned> = U0;
240 type BitOr<T: IBitMask> = T;
241 type Shift<O: Unsigned> = End;
242 type BitAnd<T: IBitMask> = End;
243 type HasFreeByteAt<O: Unsigned> = B0;
244 type ExtractBit = End;
245 type ExtractedBitMask = Saturator;
246 type ExtractedBitByteOffset = Saturator;
247}
248impl<Offset: Unsigned, T: NonZero, Rest: IBitMask> IBitMask for Array<Offset, T, Rest> {
249 const TUPLE: Self::Tuple = ((Offset::USIZE, T::USIZE), Rest::TUPLE);
250 type Tuple = ((usize, usize), Rest::Tuple);
251 type ByteAt<O: Unsigned> = <Offset::Equal<O> as Bit>::UTernary<T, Rest::ByteAt<O>>;
252 type BitAnd<Mask: IBitMask> =
253 <<T::BitAnd<Mask::ByteAt<Offset>> as Unsigned>::Equal<U0> as Bit>::BmTernary<
254 Rest::BitAnd<Mask>,
255 Array<
256 Offset,
257 <T::BitAnd<Mask::ByteAt<Offset>> as Unsigned>::NonZero,
258 Rest::BitAnd<Mask>,
259 >,
260 >;
261 type BitOr<Arr: IBitMask> = Array<Offset, T, Rest::BitOr<Arr>>;
262 type Shift<O: Unsigned> = Array<Offset::Add<O>, T, Rest::Shift<O>>;
263 type HasFreeByteAt<O: Unsigned> =
264 <<O::Equal<Offset> as Bit>::And<T::Equal<UxFF>> as Bit>::Or<Rest::HasFreeByteAt<O>>;
265 type ExtractBit =
266 <<T::AbsSub<T::TruncateAtRightmostOne> as Unsigned>::Greater<U0> as Bit>::BmTernary<
267 Array<Offset, <T::AbsSub<T::TruncateAtRightmostOne> as Unsigned>::NonZero, Rest>,
268 Rest,
269 >;
270 type ExtractedBitByteOffset = Offset;
271 type ExtractedBitMask = T::TruncateAtRightmostOne;
272}
273pub trait IForbiddenValues {
275 type Shift<O: Unsigned>: IForbiddenValues;
277 type Or<T: IForbiddenValues>: IForbiddenValues;
279 type SelectFrom<Mask: IBitMask>: ISingleForbiddenValue;
281 type SelectOne: ISingleForbiddenValue;
283 unsafe fn is_invalid(ptr: *const u8) -> bool;
288}
289pub trait ISingleForbiddenValue {
291 type Push<O: Unsigned, T>: ISingleForbiddenValue;
293 type Or<T: ISingleForbiddenValue>: ISingleForbiddenValue;
295 type And<T: ISingleForbiddenValue>: ISingleForbiddenValue;
297 type Resolve: ISingleForbiddenValue;
299}
300impl IForbiddenValues for End {
301 type Shift<O: Unsigned> = End;
302 type Or<T: IForbiddenValues> = T;
303 type SelectFrom<Mask: IBitMask> = End;
304 type SelectOne = End;
305 unsafe fn is_invalid(_: *const u8) -> bool {
306 false
307 }
308}
309impl ISingleForbiddenValue for Saturator {
310 type Push<O: Unsigned, T> = Saturator;
311 type Or<T: ISingleForbiddenValue> = T;
312 type And<T: ISingleForbiddenValue> = Saturator;
313 type Resolve = End;
314}
315impl ISingleForbiddenValue for End {
316 type Push<O: Unsigned, T> = Array<O, T, Self>;
317 type Or<T: ISingleForbiddenValue> = T;
318 type And<T: ISingleForbiddenValue> = T;
319 type Resolve = Self;
320}
321impl<Offset: Unsigned, T, Rest: ISingleForbiddenValue> ISingleForbiddenValue
322 for Array<Offset, T, Rest>
323{
324 type Push<O: Unsigned, V> = Array<O, V, Self>;
325 type Or<V: ISingleForbiddenValue> = Self;
326 type And<V: ISingleForbiddenValue> = V;
327 type Resolve = Self;
328}
329impl<Offset: Unsigned, T: Unsigned, Rest: IForbiddenValues> IForbiddenValues
330 for Array<Offset, T, Rest>
331{
332 type Shift<O: Unsigned> = Array<Offset::Add<O>, T, Rest::Shift<O>>;
333 type Or<O: IForbiddenValues> = Or<O, Self>;
334 type SelectFrom<Mask: IBitMask> =
335 <<Mask::HasFreeByteAt<Offset> as IBitBase>::AsForbiddenValue as ISingleForbiddenValue>::And<
336 <Rest::SelectFrom<Mask> as ISingleForbiddenValue>::Push<Offset, T>,
337 >;
338 type SelectOne = Array<Offset, T, Rest::SelectOne>;
339 unsafe fn is_invalid(ptr: *const u8) -> bool {
340 ptr.add(Offset::USIZE).read() == T::U8 && Rest::is_invalid(ptr)
341 }
342}
343impl<A: IForbiddenValues, B: IForbiddenValues> IForbiddenValues for Or<A, B> {
344 type Shift<O: Unsigned> = Or<A::Shift<O>, B::Shift<O>>;
345 type Or<T: IForbiddenValues> = Or<T, Self>;
346 type SelectFrom<Mask: IBitMask> =
347 <A::SelectFrom<Mask> as ISingleForbiddenValue>::Or<B::SelectFrom<Mask>>;
348 type SelectOne = A::SelectOne;
349 unsafe fn is_invalid(ptr: *const u8) -> bool {
350 A::is_invalid(ptr) || B::is_invalid(ptr)
351 }
352}
353pub struct ForbiddenRange<Min: Unsigned, Max: Unsigned<Greater<Min> = B1>, Offset: Unsigned>(
355 core::marker::PhantomData<(Min, Max, Offset)>,
356);
357impl<Min: Unsigned, Max: Unsigned<Greater<Min> = B1>, Offset: Unsigned> IForbiddenValues
358 for ForbiddenRange<Min, Max, Offset>
359{
360 type Shift<O: Unsigned> = ForbiddenRange<Min, Max, Offset::Add<O>>;
361 type Or<T: IForbiddenValues> = Or<Self, T>;
362 type SelectFrom<Mask: IBitMask> =
363 <Mask::HasFreeByteAt<Offset> as IBitBase>::_SfvTernary<Self::SelectOne, End>;
364 type SelectOne = Array<Offset, Min, End>;
365 unsafe fn is_invalid(ptr: *const u8) -> bool {
366 let v = ptr.add(Offset::USIZE).read();
367 Min::U8 <= v && v <= Max::U8
368 }
369}
370pub struct Or<A, B>(core::marker::PhantomData<(A, B)>);
372pub trait IsEnd {
374 type Output: Bit;
376}
377impl IsEnd for End {
378 type Output = B1;
379}
380impl<O: Unsigned, T, R: IBitMask> IsEnd for Array<O, T, R> {
381 type Output = B0;
382}
383
384unsafe impl<A: IStable, B: IStable> IStable for FieldPair<A, B> {
386 type ForbiddenValues =
387 Or<A::ForbiddenValues, <AlignedAfter<B, A::Size> as IStable>::ForbiddenValues>;
388 type UnusedBits =
389 <A::UnusedBits as IBitMask>::BitOr<<AlignedAfter<B, A::Size> as IStable>::UnusedBits>;
390 type Size = <AlignedAfter<B, A::Size> as IStable>::Size;
391 type Align = <A::Align as Alignment>::Max<B::Align>;
392 type HasExactlyOneNiche =
393 <<Self::Size as Unsigned>::Equal<<A::Size as Unsigned>::Add<B::Size>> as Bit>::SaddTernary<
394 <A::HasExactlyOneNiche as ISaturatingAdd>::SaturatingAdd<
395 <AlignedAfter<B, A::Size> as IStable>::HasExactlyOneNiche,
396 >,
397 Saturator,
398 >;
399 type ContainsIndirections = <A::ContainsIndirections as Bit>::Or<B::ContainsIndirections>;
400 #[cfg(feature = "experimental-ctypes")]
401 type CType = ();
402 primitive_report!("FP");
403}
404pub enum SaturatingAddValue {
406 B0,
408 B1,
410 Saturator,
412}
413pub trait ISaturatingAdd {
415 const VALUE: SaturatingAddValue;
417 type SaturatingAddB1: ISaturatingAdd;
419 type SaturatingAdd<B: ISaturatingAdd>: ISaturatingAdd;
421}
422impl ISaturatingAdd for B0 {
423 const VALUE: SaturatingAddValue = SaturatingAddValue::B0;
424 type SaturatingAdd<B: ISaturatingAdd> = B;
425 type SaturatingAddB1 = B1;
426}
427impl ISaturatingAdd for B1 {
428 const VALUE: SaturatingAddValue = SaturatingAddValue::B1;
429 type SaturatingAddB1 = Saturator;
430 type SaturatingAdd<B: ISaturatingAdd> = B::SaturatingAddB1;
431}
432impl ISaturatingAdd for Saturator {
433 const VALUE: SaturatingAddValue = SaturatingAddValue::Saturator;
434 type SaturatingAddB1 = Saturator;
435 type SaturatingAdd<B: ISaturatingAdd> = Saturator;
436}
437#[derive(Default)]
438pub struct Saturator;
440
441pub trait Includes<SubSet> {
443 type Output;
445}
446impl<T> Includes<End> for T {
447 type Output = End;
448}
449impl<O: Unsigned, T, R: IBitMask> Includes<Array<O, T, R>> for End {
450 type Output = End;
451}
452impl<O1: Unsigned, T1, R1: IBitMask, O2: Unsigned, T2, R2: IBitMask> Includes<Array<O1, T1, R1>>
453 for Array<O2, T2, R2>
454where
455 Array<O2, T2, R2>: IncludesComputer<(O1, T1)> + Includes<R1>,
456 R1: IsEnd,
457 <Self as Includes<R1>>::Output: IsEnd,
458 (
459 <Self as IncludesComputer<(O1, T1)>>::Output,
460 <Self as Includes<R1>>::Output,
461 <<Self as Includes<R1>>::Output as IsEnd>::Output,
462 <R1 as IsEnd>::Output,
463 ): Arrayify,
464{
465 type Output = <(
466 <Self as IncludesComputer<(O1, T1)>>::Output,
467 <Self as Includes<R1>>::Output,
468 <<Self as Includes<R1>>::Output as IsEnd>::Output,
469 <R1 as IsEnd>::Output,
470 ) as Arrayify>::Output;
471}
472impl<O1: Unsigned, T1> Arrayify for ((O1, T1), End, B1, B1) {
473 type Output = Array<O1, T1, End>;
474}
475impl<O1: Unsigned, T1> Arrayify for ((O1, T1), End, B1, B0) {
476 type Output = End;
477}
478impl<O1: Unsigned, T1, Tail: IBitMask> Arrayify for ((O1, T1), Tail, B0, B0) {
479 type Output = Array<O1, T1, Tail>;
480}
481impl<Tail, T, U> Arrayify for (End, Tail, T, U) {
482 type Output = End;
483}
484pub trait Arrayify {
486 type Output;
488}
489pub trait IncludesComputer<SubSet> {
491 type Output;
493}
494impl<O1: Unsigned, T1, O2: Unsigned, T2, R2: IBitMask> IncludesComputer<(O1, T1)>
495 for Array<O2, T2, R2>
496where
497 Self: IncludesComputer<(O1, T1, tyeval!(O1 == O2))>,
498{
499 type Output = <Self as IncludesComputer<(O1, T1, tyeval!(O1 == O2))>>::Output;
500}
501impl<O1: Unsigned, T1, O2: Unsigned, T2, R2: IBitMask> IncludesComputer<(O1, T1, B0)>
502 for Array<O2, T2, R2>
503where
504 R2: IncludesComputer<(O1, T1)>,
505{
506 type Output = <R2 as IncludesComputer<(O1, T1)>>::Output;
507}
508impl<O1: Unsigned, T1, O2: Unsigned, T2: Unsigned, R2: IBitMask> IncludesComputer<(O1, T1, B1)>
509 for Array<O2, T2, R2>
510where
511 Self: IncludesComputer<(O1, T1, B1, tyeval!(T2 == U255))>,
512{
513 type Output = <Self as IncludesComputer<(O1, T1, B1, tyeval!(T2 == U255))>>::Output;
514}
515impl<O1: Unsigned, T1, O2: Unsigned, T2, R2: IBitMask> IncludesComputer<(O1, T1, B1, B1)>
516 for Array<O2, T2, R2>
517{
518 type Output = (O1, T1);
519}
520impl<O1: Unsigned, T1, O2: Unsigned, T2, R2: IBitMask> IncludesComputer<(O1, T1, B1, B0)>
521 for Array<O2, T2, R2>
522{
523 type Output = End;
524}
525
526unsafe impl<A: IStable, B: IStable> IStable for Union<A, B> {
528 type ForbiddenValues = End;
529 type UnusedBits = End;
530 type Size = <<A::Size as Unsigned>::Max<B::Size> as Unsigned>::NextMultipleOf<Self::Align>;
531 type Align = <A::Align as Alignment>::Max<B::Align>;
532 type HasExactlyOneNiche = B0;
533 type ContainsIndirections = <A::ContainsIndirections as Bit>::Or<B::ContainsIndirections>;
534 #[cfg(feature = "experimental-ctypes")]
535 type CType = <<Self::Align as PowerOf2>::Divide<Self::Size> as IUnsignedBase>::Array<
536 <Self::Align as Alignment>::AsUint,
537 >;
538 primitive_report!("Union");
539}
540
541pub struct AlignedAfter<T, Start: Unsigned>(core::marker::PhantomData<(T, Start)>);
543
544unsafe impl<T: IStable, Start: Unsigned> IStable for AlignedAfter<T, Start> {
546 type Align = T::Align;
547 type Size = <T::Size as Unsigned>::Add<Start::NextMultipleOf<T::Align>>;
548 type ForbiddenValues =
549 <T::ForbiddenValues as IForbiddenValues>::Shift<Start::NextMultipleOf<T::Align>>;
550 type UnusedBits = <<<tyeval!(Start::NextMultipleOf<T::Align> - Start) as IUnsignedBase>::PaddingBitMask as IBitMask>::Shift<Start> as IBitMask>::BitOr<
551 <T::UnusedBits as IBitMask>::Shift<Start::NextMultipleOf<T::Align>>,
552 >;
553 type HasExactlyOneNiche = T::HasExactlyOneNiche;
554 type ContainsIndirections = T::ContainsIndirections;
555 #[cfg(feature = "experimental-ctypes")]
556 type CType = ();
557 primitive_report!("FP");
558}
559
560unsafe impl<T: IStable> IStable for Struct<T> {
562 type Size = <T::Size as Unsigned>::NextMultipleOf<T::Align>;
563 type Align = T::Align;
564 type ForbiddenValues = T::ForbiddenValues;
565 type UnusedBits = <T::UnusedBits as IBitMask>::BitOr<
566 <<tyeval!(<T::Size as Unsigned>::NextMultipleOf<T::Align> - T::Size) as IUnsignedBase>::PaddingBitMask as IBitMask>::Shift<T::Size>>;
567 type HasExactlyOneNiche = <<T::Size as Unsigned>::Equal<Self::Size> as Bit>::SaddTernary<
568 T::HasExactlyOneNiche,
569 Saturator,
570 >;
571 type ContainsIndirections = T::ContainsIndirections;
572 #[cfg(feature = "experimental-ctypes")]
573 type CType = ();
574 primitive_report!("FP");
575}
576
577unsafe impl<T: IStable, Align: Alignment> IStable for AlignedStruct<T, Align> {
579 type Size = <T::Size as Unsigned>::NextMultipleOf<Self::Align>;
580 type Align = <Align as Alignment>::Max<T::Align>;
581 type ForbiddenValues = T::ForbiddenValues;
582 type UnusedBits = <T::UnusedBits as IBitMask>::BitOr<
583 <<tyeval!(<T::Size as Unsigned>::NextMultipleOf<T::Align> - T::Size) as IUnsignedBase>::PaddingBitMask as IBitMask>::Shift<T::Size>>;
584 type HasExactlyOneNiche = <<T::Size as Unsigned>::Equal<Self::Size> as Bit>::SaddTernary<
585 T::HasExactlyOneNiche,
586 Saturator,
587 >;
588 type ContainsIndirections = T::ContainsIndirections;
589 #[cfg(feature = "experimental-ctypes")]
590 type CType = ();
591 primitive_report!("FP");
592}
593
594#[crate::stabby]
596pub struct _Self;