@@ -502,6 +502,215 @@ pub unsafe trait FromBytes: FromZeroes {
502
502
}
503
503
}
504
504
505
+ /// TODO
506
+ ///
507
+ /// # Safety
508
+ ///
509
+ /// `AsMaybeUninit` must only be implemented for types which are `Sized` or
510
+ /// whose last field is a slice whose element type is `Sized` (this includes
511
+ /// slice types themselves; in a slice type, the "last field" simply refers to
512
+ /// the slice itself).
513
+ pub unsafe trait AsMaybeUninit {
514
+ /// TODO
515
+ ///
516
+ /// # Safety
517
+ ///
518
+ /// For `T: AsMaybeUninit`, the following must hold:
519
+ /// - Given `m: T::MaybeUninit`, it is sound to write uninitialized bytes at
520
+ /// every byte offset in `m` (this description avoids the "what lengths
521
+ /// are valid" problem)
522
+ /// - `T` and `T::MaybeUninit` have the same alignment requirement (can't
523
+ /// use `align_of` to describe this because it requires that its argument
524
+ /// is sized)
525
+ /// - `T` and `T::MaybeUninit` are either both `Sized` or both `!Sized`
526
+ /// - If they are `Sized`, `size_of::<T>() == size_of::<T::MaybeUninit>()`
527
+ /// - If they are `!Sized`, then they are both DSTs with a trailing slice.
528
+ /// Given `t: &T` and `m: &T::MaybeUninit` with the same number of
529
+ /// elements in their trailing slices, `size_of_val(t) == size_of_val(m)`.
530
+ type MaybeUninit : ?Sized ;
531
+ }
532
+
533
+ unsafe impl < T : Sized > AsMaybeUninit for T {
534
+ type MaybeUninit = MaybeUninit < T > ;
535
+ }
536
+
537
+ unsafe impl < T : Sized > AsMaybeUninit for [ T ] {
538
+ type MaybeUninit = [ MaybeUninit < T > ] ;
539
+ }
540
+
541
+ /// A value which might or might not constitute a valid instance of `T`.
542
+ ///
543
+ /// `MaybeValid<T>` has the same layout (size and alignment) and field offsets
544
+ /// as `T`. However, it may contain any bit pattern with a few restrictions:
545
+ /// Given `m: MaybeValid<T>` and a byte offset, `b` in the range `[0,
546
+ /// size_of::<MaybeValid<T>>())`:
547
+ /// - If, in all valid instances `t: T`, the byte at offset `b` in `t` is
548
+ /// initialized, then the byte at offset `b` within `m` is guaranteed to be
549
+ /// initialized.
550
+ /// - Let `s` be the sequence of bytes of length `b` in the offset range `[0,
551
+ /// b)` in `m`. Let `TT` be the subset of valid instances of `T` which contain
552
+ /// this sequence in the offset range `[0, b)`. If, for all instances of `t:
553
+ /// T` in `TT`, the byte at offset `b` in `t` is initialized, then the byte at
554
+ /// offset `b` in `m` is guaranteed to be initialized.
555
+ ///
556
+ /// Pragmatically, this means that if `m` is guaranteed to contain an enum
557
+ /// type at a particular offset, and the enum discriminant stored in `m`
558
+ /// corresponds to a valid variant of that enum type, then it is guaranteed
559
+ /// that the appropriate bytes of `m` are initialized as defined by that
560
+ /// variant's layout (although note that the variant's layout may contain
561
+ /// another enum type, in which case the same rules apply depending on the
562
+ /// state of its discriminant, and so on recursively).
563
+ ///
564
+ /// # Safety
565
+ ///
566
+ /// TODO (make sure to mention enum layout)
567
+ #[ repr( transparent) ]
568
+ pub struct MaybeValid < T : AsMaybeUninit + ?Sized > {
569
+ inner : T :: MaybeUninit ,
570
+ }
571
+
572
+ impl < T > MaybeValid < T > {
573
+ /// TODO
574
+ pub const unsafe fn assume_valid ( self ) -> T {
575
+ unsafe { self . inner . assume_init ( ) }
576
+ }
577
+ }
578
+
579
+ impl < T > MaybeValid < [ T ] > {
580
+ /// TODO
581
+ pub const fn as_slice_of_maybe_valids ( & self ) -> & [ MaybeValid < T > ] {
582
+ let inner: & [ <T as AsMaybeUninit >:: MaybeUninit ] = & self . inner ;
583
+ // SAFETY: Since `inner` is a `&[T::MaybeUninit]`, and `MaybeValid<T>`
584
+ // is a `repr(transparent)` struct around `T::MaybeUninit`, `inner` has
585
+ // the same layout as `&[MaybeValid<T>]`.
586
+ unsafe { mem:: transmute ( inner) }
587
+ }
588
+ }
589
+
590
+ unsafe impl < T , F > Projectable < F , MaybeValid < F > > for MaybeValid < T > {
591
+ type Inner = T ;
592
+ }
593
+
594
+ impl < T > From < ByteArray < T > > for MaybeValid < T > {
595
+ fn from ( bytes : ByteArray < T > ) -> MaybeValid < T > {
596
+ todo ! ( )
597
+ }
598
+ }
599
+
600
+ impl < ' a , T > From < & ' a Align < ByteArray < T > , T > > for & ' a MaybeValid < T > {
601
+ fn from ( bytes : & ' a Align < ByteArray < T > , T > ) -> & ' a MaybeValid < T > {
602
+ todo ! ( )
603
+ }
604
+ }
605
+
606
+ impl < ' a , T > From < & ' a mut Align < ByteArray < T > , T > > for & ' a mut MaybeValid < T > {
607
+ fn from ( bytes : & ' a mut Align < ByteArray < T > , T > ) -> & ' a mut MaybeValid < T > {
608
+ todo ! ( )
609
+ }
610
+ }
611
+
612
+ impl < T > Debug for MaybeValid < T > {
613
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
614
+ f. pad ( core:: any:: type_name :: < Self > ( ) )
615
+ }
616
+ }
617
+
618
+ /// TODO
619
+ pub unsafe trait TryFromBytes : AsMaybeUninit {
620
+ /// TODO
621
+ fn is_bit_valid ( candidate : & MaybeValid < Self > ) -> bool ;
622
+
623
+ /// TODO
624
+ // Note that, in a future in which we distinguish between `FromBytes` and `RefFromBytes`,
625
+ // this requires `where Self: RefFromBytes` to disallow interior mutability.
626
+ fn try_from_ref ( bytes : & [ u8 ] ) -> Option < & Self >
627
+ where
628
+ // TODO: Remove this bound.
629
+ Self : Sized ,
630
+ {
631
+ let byte_array: & ByteArray < Self > = TryFrom :: try_from ( bytes) . ok ( ) ?;
632
+ let aligned = Align :: try_from_ref ( byte_array) ?;
633
+
634
+ if Self :: is_bit_valid ( aligned. into ( ) ) {
635
+ Some ( unsafe { & * bytes. as_ptr ( ) . cast :: < Self > ( ) } )
636
+ } else {
637
+ None
638
+ }
639
+ }
640
+
641
+ /// TODO
642
+ fn try_from_mut ( bytes : & mut [ u8 ] ) -> Option < & mut Self >
643
+ where
644
+ // TODO: Remove the `Sized` bound.
645
+ Self : AsBytes + Sized ,
646
+ {
647
+ let byte_array: & ByteArray < Self > = TryFrom :: try_from ( & * bytes) . ok ( ) ?;
648
+ let aligned = Align :: try_from_ref ( byte_array) ?;
649
+
650
+ if Self :: is_bit_valid ( aligned. into ( ) ) {
651
+ Some ( unsafe { & mut * bytes. as_mut_ptr ( ) . cast :: < Self > ( ) } )
652
+ } else {
653
+ None
654
+ }
655
+ }
656
+
657
+ /// TODO
658
+ fn try_read_from ( bytes : & [ u8 ] ) -> Option < Self >
659
+ where
660
+ Self : Sized ,
661
+ // TODO: Why can't Rust infer this based on the blanket impl for `T:
662
+ // Sized`? It sets `MaybeUninit = MaybeUninit<T>`, which is `Sized`.
663
+ <Self as AsMaybeUninit >:: MaybeUninit : Sized ,
664
+ {
665
+ let byte_array: & ByteArray < Self > = TryFrom :: try_from ( bytes) . ok ( ) ?;
666
+ let maybe_valid = MaybeValid :: from ( byte_array. clone ( ) ) ;
667
+
668
+ if Self :: is_bit_valid ( & maybe_valid) {
669
+ Some ( unsafe { maybe_valid. assume_valid ( ) } )
670
+ } else {
671
+ None
672
+ }
673
+ }
674
+ }
675
+
676
+ unsafe impl < T : FromBytes > TryFromBytes for T {
677
+ fn is_bit_valid ( _candidate : & MaybeValid < T > ) -> bool {
678
+ true
679
+ }
680
+ }
681
+
682
+ unsafe impl < T : TryFromBytes + Sized > TryFromBytes for [ T ]
683
+ where
684
+ // TODO: Why can't Rust infer this based on the blanket impl for `T: Sized`?
685
+ // It sets `MaybeUninit = MaybeUninit<T>`, which is `Sized`.
686
+ <T as AsMaybeUninit >:: MaybeUninit : Sized ,
687
+ {
688
+ fn is_bit_valid ( candidate : & MaybeValid < [ T ] > ) -> bool {
689
+ candidate. as_slice_of_maybe_valids ( ) . iter ( ) . all ( |c| T :: is_bit_valid ( c) )
690
+ }
691
+ }
692
+
693
+ mod try_from_bytes_derive_example {
694
+ use super :: * ;
695
+
696
+ struct Foo {
697
+ a : u8 ,
698
+ b : u16 ,
699
+ }
700
+
701
+ impl_try_from_bytes ! ( Foo { a: u8 , b: u16 } ) ;
702
+
703
+ struct Bar ( Foo ) ;
704
+
705
+ impl Bar {
706
+ fn is_valid ( & self ) -> bool {
707
+ u16:: from ( self . 0 . a ) < self . 0 . b
708
+ }
709
+ }
710
+
711
+ impl_try_from_bytes ! ( Bar { 0 : Foo } => is_valid) ;
712
+ }
713
+
505
714
/// Types which are safe to treat as an immutable byte slice.
506
715
///
507
716
/// WARNING: Do not implement this trait yourself! Instead, use
@@ -1543,21 +1752,9 @@ impl<T: Display + ?Sized, A> Display for Align<T, A> {
1543
1752
}
1544
1753
}
1545
1754
1546
- unsafe impl < T : ?Sized , A > Projectable for Align < T , A > {
1547
- type Inner = T ;
1548
- // SAFETY: We know that `U` can't be more aligned than `T` or else it
1549
- // couldn't be a field in `T`. Thus, any `U` within `Align<T, A>` is already
1550
- // aligned to `max(align_of::<U>(), align_of::<A>())`.
1551
- type Wrapped < U > = Align < U , A > ;
1552
-
1553
- fn foo ( & self ) -> * const T {
1554
- self as * const Self as * const T
1555
- }
1556
-
1557
- fn foo_mut ( & mut self ) -> * mut T {
1558
- self as * mut Self as * mut T
1559
- }
1560
- }
1755
+ // unsafe impl<T: ?Sized, F: ?Sized, A> Projectable<F, Align<F, A>> for Align<T, A> {
1756
+ // type Inner = T;
1757
+ // }
1561
1758
1562
1759
/// A type with no alignment requirement.
1563
1760
///
@@ -2171,18 +2368,9 @@ impl<T> Ord for ByteArray<T> {
2171
2368
}
2172
2369
}
2173
2370
2174
- unsafe impl < T > Projectable for ByteArray < T > {
2175
- type Inner = T ;
2176
- type Wrapped < U > = ByteArray < U > ;
2177
-
2178
- fn foo ( & self ) -> * const T {
2179
- self as * const Self as * const T
2180
- }
2181
-
2182
- fn foo_mut ( & mut self ) -> * mut T {
2183
- self as * mut Self as * mut T
2184
- }
2185
- }
2371
+ // unsafe impl<T, F> Projectable<F, ByteArray<F>> for ByteArray<T> {
2372
+ // type Inner = T;
2373
+ // }
2186
2374
2187
2375
// Used in `transmute!` below.
2188
2376
#[ doc( hidden) ]
0 commit comments