|
9 | 9 | use core::{fmt, hash::Hash}; |
10 | 10 |
|
11 | 11 | use super::*; |
| 12 | +use crate::pointer::{invariant::Valid, SizeEq, TransmuteFrom}; |
12 | 13 |
|
13 | 14 | /// A type with no alignment requirement. |
14 | 15 | /// |
@@ -594,6 +595,94 @@ impl<T: ?Sized + KnownLayout> fmt::Debug for MaybeUninit<T> { |
594 | 595 | } |
595 | 596 | } |
596 | 597 |
|
| 598 | +/// TODO |
| 599 | +#[cfg_attr(any(feature = "derive", test), derive(FromBytes, IntoBytes, Unaligned))] |
| 600 | +#[repr(transparent)] |
| 601 | +pub struct ReadOnly<T: ?Sized>(T); |
| 602 | + |
| 603 | +const _: () = unsafe { |
| 604 | + unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] ReadOnly<T>); |
| 605 | +}; |
| 606 | + |
| 607 | +// SAFETY: |
| 608 | +// - `ReadOnly<T>` has the same alignment as `T`, and so it is `Unaligned` |
| 609 | +// exactly when `T` is as well. |
| 610 | +// - `ReadOnly<T>` has the same bit validity as `T`, and so it is `FromZeros`, |
| 611 | +// `FromBytes`, or `IntoBytes` exactly when `T` is as well. |
| 612 | +// - `TryFromBytes`: `ReadOnly<T>` has the same the same bit validity as `T`, so |
| 613 | +// `T::is_bit_valid` is a sound implementation of `is_bit_valid`. |
| 614 | +#[allow(unused_unsafe)] // Unused when `feature = "derive"`. |
| 615 | +const _: () = unsafe { |
| 616 | + impl_or_verify!(T: ?Sized + Unaligned => Unaligned for ReadOnly<T>); |
| 617 | + impl_or_verify!( |
| 618 | + T: ?Sized + TryFromBytes => TryFromBytes for ReadOnly<T>; |
| 619 | + |c| T::is_bit_valid(c.transmute::<_, _, BecauseImmutable>()) |
| 620 | + ); |
| 621 | + impl_or_verify!(T: ?Sized + FromZeros => FromZeros for ReadOnly<T>); |
| 622 | + impl_or_verify!(T: ?Sized + FromBytes => FromBytes for ReadOnly<T>); |
| 623 | + impl_or_verify!(T: ?Sized + IntoBytes => IntoBytes for ReadOnly<T>); |
| 624 | +}; |
| 625 | + |
| 626 | +const _: () = unsafe { |
| 627 | + unsafe_impl!(T: ?Sized => Immutable for ReadOnly<T>); |
| 628 | +}; |
| 629 | + |
| 630 | +const _: () = { |
| 631 | + // SAFETY: TODO |
| 632 | + define_cast!(unsafe { pub CastFromReadOnly<T: ?Sized> = ReadOnly<T> => T}); |
| 633 | + // SAFETY: TODO |
| 634 | + define_cast!(unsafe { pub CastToReadOnly<T: ?Sized> = T => ReadOnly<T>}); |
| 635 | + |
| 636 | + unsafe impl<T: ?Sized> SizeEq<ReadOnly<T>> for T { |
| 637 | + type CastFrom = CastFromReadOnly; |
| 638 | + } |
| 639 | + |
| 640 | + unsafe impl<T: ?Sized> SizeEq<T> for ReadOnly<T> { |
| 641 | + type CastFrom = CastToReadOnly; |
| 642 | + } |
| 643 | +}; |
| 644 | + |
| 645 | +unsafe impl<T: ?Sized> TransmuteFrom<T, Valid, Valid> for ReadOnly<T> {} |
| 646 | +unsafe impl<T: ?Sized> TransmuteFrom<ReadOnly<T>, Valid, Valid> for T {} |
| 647 | + |
| 648 | +impl<T> ReadOnly<T> { |
| 649 | + /// TODO |
| 650 | + #[inline(always)] |
| 651 | + pub const fn new(t: T) -> ReadOnly<T> { |
| 652 | + ReadOnly(t) |
| 653 | + } |
| 654 | +} |
| 655 | + |
| 656 | +impl<T: ?Sized + Immutable> Deref for ReadOnly<T> { |
| 657 | + type Target = T; |
| 658 | + |
| 659 | + #[inline(always)] |
| 660 | + fn deref(&self) -> &Self::Target { |
| 661 | + &self.0 |
| 662 | + } |
| 663 | +} |
| 664 | + |
| 665 | +impl<T: ?Sized + Immutable> DerefMut for ReadOnly<T> { |
| 666 | + #[inline(always)] |
| 667 | + fn deref_mut(&mut self) -> &mut Self::Target { |
| 668 | + &mut self.0 |
| 669 | + } |
| 670 | +} |
| 671 | + |
| 672 | +impl<'a, T: ?Sized + Immutable> From<&'a T> for &'a ReadOnly<T> { |
| 673 | + #[inline(always)] |
| 674 | + fn from(t: &'a T) -> &'a ReadOnly<T> { |
| 675 | + todo!() |
| 676 | + } |
| 677 | +} |
| 678 | + |
| 679 | +impl<T: ?Sized + Immutable + Debug> Debug for ReadOnly<T> { |
| 680 | + #[inline(always)] |
| 681 | + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 682 | + self.deref().fmt(f) |
| 683 | + } |
| 684 | +} |
| 685 | + |
597 | 686 | #[cfg(test)] |
598 | 687 | mod tests { |
599 | 688 | use core::panic::AssertUnwindSafe; |
|
0 commit comments