Skip to content

Commit ba5b262

Browse files
committed
[WIP] ReadOnly
gherrit-pr-id: Gbe8d7edd150d80731c79815685c596ed88460ae7
1 parent 6414d5d commit ba5b262

2 files changed

Lines changed: 184 additions & 1 deletion

File tree

src/pointer/mod.rs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ where
4141

4242
#[doc(hidden)]
4343
pub mod cast {
44-
use core::{marker::PhantomData, mem};
44+
use core::{
45+
marker::PhantomData,
46+
mem::{self, MaybeUninit},
47+
num::Wrapping,
48+
};
4549

4650
use crate::{
4751
layout::{SizeInfo, TrailingSliceLayout},
@@ -193,6 +197,74 @@ pub mod cast {
193197
}
194198
}
195199

200+
/// TODO
201+
///
202+
/// # Safety
203+
///
204+
/// TODO
205+
pub unsafe trait Wrapped {
206+
type Unwrapped: ?Sized;
207+
type CastToUnwrapped: Cast<Self, Self::Unwrapped>;
208+
}
209+
210+
/// TODO
211+
///
212+
/// # Safety
213+
///
214+
/// TODO
215+
pub unsafe trait HasWrappedField<F: ?Sized>: Wrapped {
216+
type WrappedField: ?Sized;
217+
218+
type CastToWrappedField: Cast<F, Self::WrappedField>;
219+
}
220+
221+
// SAFETY: TODO
222+
unsafe impl<T> Wrapped for MaybeUninit<T> {
223+
type Unwrapped = T;
224+
type CastToUnwrapped = CastSized;
225+
}
226+
227+
// SAFETY: TODO
228+
unsafe impl<T, F> HasWrappedField<F> for MaybeUninit<T> {
229+
type WrappedField = MaybeUninit<F>;
230+
type CastToWrappedField = CastSized;
231+
}
232+
233+
// SAFETY: TODO
234+
unsafe impl<T> Wrapped for Wrapping<T> {
235+
type Unwrapped = T;
236+
type CastToUnwrapped = CastSized;
237+
}
238+
239+
// SAFETY: TODO
240+
unsafe impl<T, F> HasWrappedField<F> for Wrapping<T> {
241+
type WrappedField = Wrapping<F>;
242+
type CastToWrappedField = CastSized;
243+
}
244+
245+
#[allow(missing_debug_implementations, missing_copy_implementations)]
246+
pub struct WrappedProjection<W: ?Sized, F, const VARIANT_ID: i128, const FIELD_ID: i128> {
247+
_never: core::convert::Infallible,
248+
_phantom: PhantomData<(F, W)>,
249+
}
250+
251+
// SAFETY: TODO
252+
unsafe impl<W: ?Sized, F, const VARIANT_ID: i128, const FIELD_ID: i128>
253+
Project<W, W::WrappedField> for WrappedProjection<W, F, VARIANT_ID, FIELD_ID>
254+
where
255+
W: Wrapped
256+
+ HasWrappedField<<<W as Wrapped>::Unwrapped as HasField<F, VARIANT_ID, FIELD_ID>>::Type>,
257+
W::Unwrapped: HasField<F, VARIANT_ID, FIELD_ID>,
258+
{
259+
#[inline(always)]
260+
fn project(src: PtrInner<'_, W>) -> *mut W::WrappedField {
261+
src.project::<_, W::CastToUnwrapped>()
262+
.project::<_, Projection<F, VARIANT_ID, FIELD_ID>>()
263+
.project::<_, W::CastToWrappedField>()
264+
.as_ptr()
265+
}
266+
}
267+
196268
/// A transitive sequence of projections.
197269
///
198270
/// Given `TU: Project` and `UV: Project`, `TransitiveProject<_, TU, UV>` is

src/wrappers.rs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use core::{fmt, hash::Hash};
1010

1111
use super::*;
12+
use crate::pointer::{invariant::Valid, SizeEq, TransmuteFrom};
1213

1314
/// A type with no alignment requirement.
1415
///
@@ -594,6 +595,116 @@ impl<T: ?Sized + KnownLayout> fmt::Debug for MaybeUninit<T> {
594595
}
595596
}
596597

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+
597708
#[cfg(test)]
598709
mod tests {
599710
use core::panic::AssertUnwindSafe;

0 commit comments

Comments
 (0)