@@ -502,6 +502,196 @@ 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
+ unsafe impl < T , F > Projectable < F , MaybeValid < F > > for MaybeValid < T > {
580
+ type Inner = T ;
581
+ }
582
+
583
+ impl < T > From < ByteArray < T > > for MaybeValid < T > {
584
+ fn from ( bytes : ByteArray < T > ) -> MaybeValid < T > {
585
+ todo ! ( )
586
+ }
587
+ }
588
+
589
+ impl < ' a , T > From < & ' a Align < ByteArray < T > , T > > for & ' a MaybeValid < T > {
590
+ fn from ( bytes : & ' a Align < ByteArray < T > , T > ) -> & ' a MaybeValid < T > {
591
+ todo ! ( )
592
+ }
593
+ }
594
+
595
+ impl < ' a , T > From < & ' a mut Align < ByteArray < T > , T > > for & ' a mut MaybeValid < T > {
596
+ fn from ( bytes : & ' a mut Align < ByteArray < T > , T > ) -> & ' a mut MaybeValid < T > {
597
+ todo ! ( )
598
+ }
599
+ }
600
+
601
+ impl < T > Debug for MaybeValid < T > {
602
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
603
+ f. pad ( core:: any:: type_name :: < Self > ( ) )
604
+ }
605
+ }
606
+
607
+ /// TODO
608
+ pub unsafe trait TryFromBytes : AsMaybeUninit {
609
+ /// TODO
610
+ fn is_bit_valid ( candidate : & MaybeValid < Self > ) -> bool ;
611
+
612
+ /// TODO
613
+ // Note that, in a future in which we distinguish between `FromBytes` and `RefFromBytes`,
614
+ // this requires `where Self: RefFromBytes` to disallow interior mutability.
615
+ fn try_from_ref ( bytes : & [ u8 ] ) -> Option < & Self >
616
+ where
617
+ // TODO: Remove this bound.
618
+ Self : Sized ,
619
+ {
620
+ let byte_array: & ByteArray < Self > = TryFrom :: try_from ( bytes) . ok ( ) ?;
621
+ let aligned = Align :: try_from_ref ( byte_array) ?;
622
+
623
+ if Self :: is_bit_valid ( aligned. into ( ) ) {
624
+ Some ( unsafe { & * bytes. as_ptr ( ) . cast :: < Self > ( ) } )
625
+ } else {
626
+ None
627
+ }
628
+ }
629
+
630
+ /// TODO
631
+ fn try_from_mut ( bytes : & mut [ u8 ] ) -> Option < & mut Self >
632
+ where
633
+ // TODO: Remove the `Sized` bound.
634
+ Self : AsBytes + Sized ,
635
+ {
636
+ let byte_array: & ByteArray < Self > = TryFrom :: try_from ( & * bytes) . ok ( ) ?;
637
+ let aligned = Align :: try_from_ref ( byte_array) ?;
638
+
639
+ if Self :: is_bit_valid ( aligned. into ( ) ) {
640
+ Some ( unsafe { & mut * bytes. as_mut_ptr ( ) . cast :: < Self > ( ) } )
641
+ } else {
642
+ None
643
+ }
644
+ }
645
+
646
+ /// TODO
647
+ fn try_read_from ( bytes : & [ u8 ] ) -> Option < Self >
648
+ where
649
+ Self : Sized ,
650
+ // TODO: Why can't Rust infer this based on the blanket impl for `T:
651
+ // Sized`? It sets `MaybeUninit = MaybeUninit<T>`, which is `Sized`.
652
+ <Self as AsMaybeUninit >:: MaybeUninit : Sized ,
653
+ {
654
+ let byte_array: & ByteArray < Self > = TryFrom :: try_from ( bytes) . ok ( ) ?;
655
+ let maybe_valid = MaybeValid :: from ( byte_array. clone ( ) ) ;
656
+
657
+ if Self :: is_bit_valid ( & maybe_valid) {
658
+ Some ( unsafe { maybe_valid. assume_valid ( ) } )
659
+ } else {
660
+ None
661
+ }
662
+ }
663
+ }
664
+
665
+ unsafe impl < T : FromBytes > TryFromBytes for T {
666
+ fn is_bit_valid ( _candidate : & MaybeValid < Self > ) -> bool
667
+ where
668
+ Self : Sized ,
669
+ {
670
+ true
671
+ }
672
+ }
673
+
674
+ mod try_from_bytes_derive_example {
675
+ use super :: * ;
676
+
677
+ struct Foo {
678
+ a : u8 ,
679
+ b : u16 ,
680
+ }
681
+
682
+ impl_try_from_bytes ! ( Foo { a: u8 , b: u16 } ) ;
683
+
684
+ struct Bar ( Foo ) ;
685
+
686
+ impl Bar {
687
+ fn is_valid ( & self ) -> bool {
688
+ u16:: from ( self . 0 . a ) < self . 0 . b
689
+ }
690
+ }
691
+
692
+ impl_try_from_bytes ! ( Bar { 0 : Foo } => is_valid) ;
693
+ }
694
+
505
695
/// Types which are safe to treat as an immutable byte slice.
506
696
///
507
697
/// WARNING: Do not implement this trait yourself! Instead, use
@@ -1543,21 +1733,9 @@ impl<T: Display + ?Sized, A> Display for Align<T, A> {
1543
1733
}
1544
1734
}
1545
1735
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
- }
1736
+ // unsafe impl<T: ?Sized, F: ?Sized, A> Projectable<F, Align<F, A>> for Align<T, A> {
1737
+ // type Inner = T;
1738
+ // }
1561
1739
1562
1740
/// A type with no alignment requirement.
1563
1741
///
@@ -2171,18 +2349,9 @@ impl<T> Ord for ByteArray<T> {
2171
2349
}
2172
2350
}
2173
2351
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
- }
2352
+ // unsafe impl<T, F> Projectable<F, ByteArray<F>> for ByteArray<T> {
2353
+ // type Inner = T;
2354
+ // }
2186
2355
2187
2356
// Used in `transmute!` below.
2188
2357
#[ doc( hidden) ]
0 commit comments