|
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,116 @@ 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 | +// SAFETY: TODO |
| 604 | +const _: () = unsafe { |
| 605 | + unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] ReadOnly<T>); |
| 606 | +}; |
| 607 | + |
| 608 | +#[allow(unused_unsafe)] // Unused when `feature = "derive"`. |
| 609 | + // SAFETY: |
| 610 | + // - `ReadOnly<T>` has the same alignment as `T`, and so it is `Unaligned` |
| 611 | + // exactly when `T` is as well. |
| 612 | + // - `ReadOnly<T>` has the same bit validity as `T`, and so it is `FromZeros`, |
| 613 | + // `FromBytes`, or `IntoBytes` exactly when `T` is as well. |
| 614 | + // - `TryFromBytes`: `ReadOnly<T>` has the same the same bit validity as `T`, so |
| 615 | + // `T::is_bit_valid` is a sound implementation of `is_bit_valid`. |
| 616 | +const _: () = unsafe { |
| 617 | + impl_or_verify!(T: ?Sized + Unaligned => Unaligned for ReadOnly<T>); |
| 618 | + impl_or_verify!( |
| 619 | + T: ?Sized + TryFromBytes => TryFromBytes for ReadOnly<T>; |
| 620 | + |c| T::is_bit_valid(c.transmute::<_, _, BecauseImmutable>()) |
| 621 | + ); |
| 622 | + impl_or_verify!(T: ?Sized + FromZeros => FromZeros for ReadOnly<T>); |
| 623 | + impl_or_verify!(T: ?Sized + FromBytes => FromBytes for ReadOnly<T>); |
| 624 | + impl_or_verify!(T: ?Sized + IntoBytes => IntoBytes for ReadOnly<T>); |
| 625 | +}; |
| 626 | + |
| 627 | +// SAFETY: TODO |
| 628 | +const _: () = unsafe { |
| 629 | + unsafe_impl!(T: ?Sized => Immutable for ReadOnly<T>); |
| 630 | +}; |
| 631 | + |
| 632 | +const _: () = { |
| 633 | + // SAFETY: TODO |
| 634 | + define_cast!(unsafe { pub CastFromReadOnly<T: ?Sized> = ReadOnly<T> => T}); |
| 635 | + // SAFETY: TODO |
| 636 | + define_cast!(unsafe { pub CastToReadOnly<T: ?Sized> = T => ReadOnly<T>}); |
| 637 | + |
| 638 | + // SAFETY: TODO |
| 639 | + unsafe impl<T: ?Sized> SizeEq<ReadOnly<T>> for T { |
| 640 | + type CastFrom = CastFromReadOnly; |
| 641 | + } |
| 642 | + |
| 643 | + // SAFETY: TODO |
| 644 | + unsafe impl<T: ?Sized> SizeEq<T> for ReadOnly<T> { |
| 645 | + type CastFrom = CastToReadOnly; |
| 646 | + } |
| 647 | + |
| 648 | + // SAFETY: TODO |
| 649 | + unsafe impl<T: ?Sized> crate::pointer::cast::Wrapped for ReadOnly<T> { |
| 650 | + type Unwrapped = T; |
| 651 | + type CastToUnwrapped = CastFromReadOnly; |
| 652 | + } |
| 653 | + |
| 654 | + // SAFETY: TODO |
| 655 | + unsafe impl<T: ?Sized, F: ?Sized> crate::pointer::cast::HasWrappedField<F> for ReadOnly<T> { |
| 656 | + type WrappedField = ReadOnly<F>; |
| 657 | + type CastToWrappedField = CastToReadOnly; |
| 658 | + } |
| 659 | +}; |
| 660 | + |
| 661 | +// SAFETY: TODO |
| 662 | +unsafe impl<T: ?Sized> TransmuteFrom<T, Valid, Valid> for ReadOnly<T> {} |
| 663 | + |
| 664 | +// SAFETY: TODO |
| 665 | +unsafe impl<T: ?Sized> TransmuteFrom<ReadOnly<T>, Valid, Valid> for T {} |
| 666 | + |
| 667 | +impl<T> ReadOnly<T> { |
| 668 | + /// TODO |
| 669 | + #[inline(always)] |
| 670 | + pub const fn new(t: T) -> ReadOnly<T> { |
| 671 | + ReadOnly(t) |
| 672 | + } |
| 673 | +} |
| 674 | + |
| 675 | +impl<'a, T: ?Sized + Immutable> From<&'a T> for &'a ReadOnly<T> { |
| 676 | + #[inline(always)] |
| 677 | + fn from(t: &'a T) -> &'a ReadOnly<T> { |
| 678 | + let ro = Ptr::from_ref(t).transmute::<_, _, (_, _)>(); |
| 679 | + // SAFETY: TODO |
| 680 | + let ro = unsafe { ro.assume_alignment() }; |
| 681 | + ro.as_ref() |
| 682 | + } |
| 683 | +} |
| 684 | + |
| 685 | +impl<T: ?Sized + Immutable> Deref for ReadOnly<T> { |
| 686 | + type Target = T; |
| 687 | + |
| 688 | + #[inline(always)] |
| 689 | + fn deref(&self) -> &Self::Target { |
| 690 | + &self.0 |
| 691 | + } |
| 692 | +} |
| 693 | + |
| 694 | +impl<T: ?Sized + Immutable> DerefMut for ReadOnly<T> { |
| 695 | + #[inline(always)] |
| 696 | + fn deref_mut(&mut self) -> &mut Self::Target { |
| 697 | + &mut self.0 |
| 698 | + } |
| 699 | +} |
| 700 | + |
| 701 | +impl<T: ?Sized + Immutable + Debug> Debug for ReadOnly<T> { |
| 702 | + #[inline(always)] |
| 703 | + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 704 | + self.deref().fmt(f) |
| 705 | + } |
| 706 | +} |
| 707 | + |
597 | 708 | #[cfg(test)] |
598 | 709 | mod tests { |
599 | 710 | use core::panic::AssertUnwindSafe; |
|
0 commit comments