1use std::{
2 marker::PhantomData,
3 ptr::Pointee,
4};
5
6use crate::*;
7
8pub trait Projection {
10 type Source: ?Sized;
11 type Target: ?Sized;
12
13 fn offset(&self, meta: <Self::Source as Pointee>::Metadata) -> usize;
14 fn project_metadata(
15 &self,
16 meta: <Self::Source as Pointee>::Metadata,
17 ) -> <Self::Target as Pointee>::Metadata;
18}
19
20impl<P: Projection + ?Sized> ProjectionExt for P {}
22pub trait ProjectionExt: Projection {
23 unsafe fn borrow<'a, X, Y>(&self, ptr: *const X) -> Y
26 where
27 X: HasPlace<Target = Self::Source>,
28 Y: HasPlace<Target = Self::Target>,
29 X: PlaceBorrow<'a, Self, Y>,
30 {
31 unsafe { PlaceBorrow::borrow(ptr, self) }
32 }
33 unsafe fn read<X>(&self, ptr: *const X) -> Self::Target
35 where
36 X: PlaceRead<Self>,
37 Self::Target: Sized,
38 {
39 unsafe { PlaceRead::read(ptr, self) }
40 }
41 unsafe fn write<X>(&self, ptr: *mut X, val: Self::Target)
43 where
44 X: PlaceWrite<Self>,
45 Self::Target: Sized,
46 {
47 unsafe { PlaceWrite::write(ptr, self, val) }
48 }
49 unsafe fn deref<X>(&self, ptr: *mut X) -> *const Self::Target
52 where
53 X: HasPlace<Target = Self::Source>,
54 X: PlaceDeref<Self>,
55 Self::Target: HasPlace,
56 {
57 unsafe { PlaceDeref::double_deref(ptr, self) }
58 }
59
60 fn as_sized(&self) -> SizedProj<Self::Source, Self::Target>
65 where
66 Self::Source: Sized,
67 Self::Target: Sized,
68 {
69 SizedProj(self.offset(()), PhantomData, PhantomData)
70 }
71
72 fn compose<Q>(self, other: Q) -> ComposeProj<Self, Q>
73 where
74 Self: Sized,
75 Q: Projection<Source = Self::Target>,
76 {
77 ComposeProj { p: self, q: other }
78 }
79}
80
81pub struct NoopProj<T: ?Sized>(PhantomData<T>);
82impl<T> Default for NoopProj<T> {
83 fn default() -> Self {
84 Self(Default::default())
85 }
86}
87impl<T> Clone for NoopProj<T> {
88 fn clone(&self) -> Self {
89 Self(self.0.clone())
90 }
91}
92impl<T: ?Sized> Projection for NoopProj<T> {
93 type Source = T;
94 type Target = T;
95 fn offset(&self, _m: <Self::Source as Pointee>::Metadata) -> usize {
96 0
97 }
98 fn project_metadata(
99 &self,
100 m: <Self::Source as Pointee>::Metadata,
101 ) -> <Self::Target as Pointee>::Metadata {
102 m
103 }
104}
105
106#[derive(#[automatically_derived]
impl<S: ::core::clone::Clone + ?Sized, T: ::core::clone::Clone>
::core::clone::Clone for SizedProj<S, T> {
#[inline]
fn clone(&self) -> SizedProj<S, T> {
SizedProj(::core::clone::Clone::clone(&self.0),
::core::clone::Clone::clone(&self.1),
::core::clone::Clone::clone(&self.2))
}
}Clone)]
108pub struct SizedProj<S: ?Sized, T>(usize, PhantomData<S>, PhantomData<T>);
109impl<S, T> Projection for SizedProj<S, T> {
110 type Source = S;
111 type Target = T;
112 fn offset(&self, _m: <Self::Source as Pointee>::Metadata) -> usize {
113 self.0
114 }
115 fn project_metadata(
116 &self,
117 _: <Self::Source as Pointee>::Metadata,
118 ) -> <Self::Target as Pointee>::Metadata {
119 }
120}
121
122#[derive(#[automatically_derived]
impl<P: ::core::clone::Clone + ?Sized, Q: ::core::clone::Clone>
::core::clone::Clone for ComposeProj<P, Q> {
#[inline]
fn clone(&self) -> ComposeProj<P, Q> {
ComposeProj {
q: ::core::clone::Clone::clone(&self.q),
p: ::core::clone::Clone::clone(&self.p),
}
}
}Clone)]
124pub struct ComposeProj<P: ?Sized, Q> {
125 q: Q,
126 p: P,
127}
128impl<P, Q> Projection for ComposeProj<P, Q>
129where
130 P: Projection + ?Sized,
131 Q: Projection<Source = P::Target>,
132{
133 type Source = P::Source;
134 type Target = Q::Target;
135 fn offset(&self, meta: <Self::Source as Pointee>::Metadata) -> usize {
136 let qmeta = self.p.project_metadata(meta);
137 self.p.offset(meta) + self.q.offset(qmeta)
138 }
139 fn project_metadata(
140 &self,
141 meta: <Self::Source as Pointee>::Metadata,
142 ) -> <Self::Target as Pointee>::Metadata {
143 self.q.project_metadata(self.p.project_metadata(meta))
144 }
145}