Skip to content

Commit e2f1bc3

Browse files
committed
[WIP] ReadOnly
gherrit-pr-id: Gbe8d7edd150d80731c79815685c596ed88460ae7
1 parent 28de514 commit e2f1bc3

2 files changed

Lines changed: 225 additions & 1 deletion

File tree

src/pointer/mod.rs

Lines changed: 110 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},
@@ -290,6 +294,111 @@ pub mod cast {
290294
}
291295
}
292296

297+
/// TODO
298+
///
299+
/// # Safety
300+
///
301+
/// TODO
302+
pub unsafe trait Wrapped {
303+
type Unwrapped: ?Sized;
304+
type CastToUnwrapped: CastExact<Self, Self::Unwrapped>;
305+
type CastFromUnwrapped: CastExact<Self::Unwrapped, Self>;
306+
}
307+
308+
/// TODO
309+
///
310+
/// # Safety
311+
///
312+
/// TODO
313+
pub unsafe trait HasWrappedField<F: ?Sized>: Wrapped {
314+
type WrappedField: ?Sized + Wrapped<Unwrapped = F>;
315+
}
316+
317+
// SAFETY: TODO
318+
unsafe impl<T> Wrapped for MaybeUninit<T> {
319+
type Unwrapped = T;
320+
type CastToUnwrapped = CastSizedExact;
321+
type CastFromUnwrapped = CastSizedExact;
322+
}
323+
324+
// SAFETY: TODO
325+
unsafe impl<T, F> HasWrappedField<F> for MaybeUninit<T> {
326+
type WrappedField = MaybeUninit<F>;
327+
}
328+
329+
// SAFETY: TODO
330+
unsafe impl<T> Wrapped for Wrapping<T> {
331+
type Unwrapped = T;
332+
type CastToUnwrapped = CastSizedExact;
333+
type CastFromUnwrapped = CastSizedExact;
334+
}
335+
336+
// SAFETY: TODO
337+
unsafe impl<T, F> HasWrappedField<F> for Wrapping<T> {
338+
type WrappedField = Wrapping<F>;
339+
}
340+
341+
#[allow(missing_debug_implementations, missing_copy_implementations)]
342+
pub struct WrappedProjection<W: ?Sized, F, const VARIANT_ID: i128, const FIELD_ID: i128> {
343+
_never: core::convert::Infallible,
344+
_phantom: PhantomData<(F, W)>,
345+
}
346+
347+
// SAFETY: TODO
348+
unsafe impl<W: ?Sized, F, const VARIANT_ID: i128, const FIELD_ID: i128>
349+
Project<W, W::WrappedField> for WrappedProjection<W, F, VARIANT_ID, FIELD_ID>
350+
where
351+
W: Wrapped
352+
+ HasWrappedField<<<W as Wrapped>::Unwrapped as HasField<F, VARIANT_ID, FIELD_ID>>::Type>,
353+
W::Unwrapped: HasField<F, VARIANT_ID, FIELD_ID>,
354+
{
355+
#[inline(always)]
356+
fn project(src: PtrInner<'_, W>) -> *mut W::WrappedField {
357+
src.project::<_, W::CastToUnwrapped>()
358+
.project::<_, Projection<F, VARIANT_ID, FIELD_ID>>()
359+
.project::<_, <W::WrappedField as Wrapped>::CastFromUnwrapped>()
360+
.as_ptr()
361+
}
362+
}
363+
364+
#[allow(missing_debug_implementations, missing_copy_implementations)]
365+
pub struct TransposeProjection<W: ?Sized, V: ?Sized> {
366+
_never: core::convert::Infallible,
367+
_phantom_w: PhantomData<W>,
368+
_phantom_v: PhantomData<V>,
369+
}
370+
371+
/*
372+
pub unsafe trait Wrapped {
373+
type Unwrapped: ?Sized;
374+
type CastToUnwrapped: CastExact<Self, Self::Unwrapped>;
375+
type CastFromUnwrapped: CastExact<Self::Unwrapped, Self>;
376+
}
377+
378+
pub unsafe trait HasWrappedField<F: ?Sized>: Wrapped {
379+
type WrappedField: ?Sized + Wrapped<Unwrapped = F>;
380+
}
381+
*/
382+
383+
// SAFETY: TODO
384+
unsafe impl<W: ?Sized, V: ?Sized> Project<
385+
W,
386+
<V as HasWrappedField<<W as HasWrappedField<V::Unwrapped>>::WrappedField>>::WrappedField
387+
> for TransposeProjection<W, V>
388+
where
389+
W: Wrapped<Unwrapped = V> + HasWrappedField<V::Unwrapped>,
390+
V: Wrapped + HasWrappedField<<W as HasWrappedField<<V as Wrapped>::Unwrapped>>::WrappedField>,
391+
{
392+
#[inline(always)]
393+
fn project(src: PtrInner<'_, W>) -> *mut <V as HasWrappedField<<W as HasWrappedField<V::Unwrapped>>::WrappedField>>::WrappedField {
394+
src.project::<_, W::CastToUnwrapped>()
395+
.project::<_, V::CastToUnwrapped>()
396+
.project::<_, <<W as HasWrappedField<V::Unwrapped>>::WrappedField as Wrapped>::CastFromUnwrapped>()
397+
.project::<_, <<V as HasWrappedField<<W as HasWrappedField<V::Unwrapped>>::WrappedField>>::WrappedField as Wrapped>::CastFromUnwrapped>()
398+
.as_ptr()
399+
}
400+
}
401+
293402
/// A transitive sequence of projections.
294403
///
295404
/// Given `TU: Project` and `UV: Project`, `TransitiveProject<_, TU, UV>` is

src/wrappers.rs

Lines changed: 115 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,120 @@ 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+
use crate::pointer::cast::CastExact;
634+
635+
// SAFETY: TODO
636+
define_cast!(unsafe { pub CastFromReadOnly<T: ?Sized> = ReadOnly<T> => T});
637+
// SAFETY: TODO
638+
unsafe impl<T: ?Sized> CastExact<ReadOnly<T>, T> for CastFromReadOnly {}
639+
// SAFETY: TODO
640+
define_cast!(unsafe { pub CastToReadOnly<T: ?Sized> = T => ReadOnly<T>});
641+
// SAFETY: TODO
642+
unsafe impl<T: ?Sized> CastExact<T, ReadOnly<T>> for CastToReadOnly {}
643+
644+
impl<T: ?Sized> SizeEq<ReadOnly<T>> for T {
645+
type CastFrom = CastFromReadOnly;
646+
}
647+
648+
impl<T: ?Sized> SizeEq<T> for ReadOnly<T> {
649+
type CastFrom = CastToReadOnly;
650+
}
651+
652+
// SAFETY: TODO
653+
unsafe impl<T: ?Sized> crate::pointer::cast::Wrapped for ReadOnly<T> {
654+
type Unwrapped = T;
655+
type CastToUnwrapped = CastFromReadOnly;
656+
type CastFromUnwrapped = CastToReadOnly;
657+
}
658+
659+
// SAFETY: TODO
660+
unsafe impl<T: ?Sized, F: ?Sized> crate::pointer::cast::HasWrappedField<F> for ReadOnly<T> {
661+
type WrappedField = ReadOnly<F>;
662+
}
663+
};
664+
665+
// SAFETY: TODO
666+
unsafe impl<T: ?Sized> TransmuteFrom<T, Valid, Valid> for ReadOnly<T> {}
667+
668+
// SAFETY: TODO
669+
unsafe impl<T: ?Sized> TransmuteFrom<ReadOnly<T>, Valid, Valid> for T {}
670+
671+
impl<T> ReadOnly<T> {
672+
/// TODO
673+
#[inline(always)]
674+
pub const fn new(t: T) -> ReadOnly<T> {
675+
ReadOnly(t)
676+
}
677+
}
678+
679+
impl<'a, T: ?Sized + Immutable> From<&'a T> for &'a ReadOnly<T> {
680+
#[inline(always)]
681+
fn from(t: &'a T) -> &'a ReadOnly<T> {
682+
let ro = Ptr::from_ref(t).transmute::<_, _, (_, _)>();
683+
// SAFETY: TODO
684+
let ro = unsafe { ro.assume_alignment() };
685+
ro.as_ref()
686+
}
687+
}
688+
689+
impl<T: ?Sized + Immutable> Deref for ReadOnly<T> {
690+
type Target = T;
691+
692+
#[inline(always)]
693+
fn deref(&self) -> &Self::Target {
694+
&self.0
695+
}
696+
}
697+
698+
impl<T: ?Sized + Immutable> DerefMut for ReadOnly<T> {
699+
#[inline(always)]
700+
fn deref_mut(&mut self) -> &mut Self::Target {
701+
&mut self.0
702+
}
703+
}
704+
705+
impl<T: ?Sized + Immutable + Debug> Debug for ReadOnly<T> {
706+
#[inline(always)]
707+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
708+
self.deref().fmt(f)
709+
}
710+
}
711+
597712
#[cfg(test)]
598713
mod tests {
599714
use core::panic::AssertUnwindSafe;

0 commit comments

Comments
 (0)