1use std::{
2 any::Any,
3 hash::{BuildHasher, Hash},
4 marker::PhantomData,
5 mem::ManuallyDrop,
6 pin::Pin,
7 task::Poll,
8};
9
10use anyhow::Result;
11use futures::Future;
12use pin_project_lite::pin_project;
13use rustc_hash::FxBuildHasher;
14
15use super::traits::VcValueType;
16use crate::{
17 MappedReadRef, ReadRawVcFuture, ReadRef, VcCast, VcValueTrait, VcValueTraitCast,
18 VcValueTypeCast,
19 keyed::{KeyedAccess, KeyedEq},
20};
21
22type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
23
24pub trait VcRead<T>
32where
33 T: VcValueType,
34{
35 type Target;
42
43 fn value_to_target_ref(value: &T) -> &Self::Target;
45
46 fn value_to_target(value: T) -> Self::Target;
48
49 fn target_to_value(target: Self::Target) -> T;
51
52 fn target_to_value_ref(target: &Self::Target) -> &T;
54
55 fn target_to_value_mut_ref(target: &mut Self::Target) -> &mut T;
57}
58
59pub struct VcDefaultRead<T> {
62 _phantom: PhantomData<T>,
63}
64
65impl<T> VcRead<T> for VcDefaultRead<T>
66where
67 T: VcValueType,
68{
69 type Target = T;
70
71 fn value_to_target_ref(value: &T) -> &Self::Target {
72 value
73 }
74
75 fn value_to_target(value: T) -> Self::Target {
76 value
77 }
78
79 fn target_to_value(target: Self::Target) -> T {
80 target
81 }
82
83 fn target_to_value_ref(target: &Self::Target) -> &T {
84 target
85 }
86
87 fn target_to_value_mut_ref(target: &mut Self::Target) -> &mut T {
88 target
89 }
90}
91
92pub struct VcTransparentRead<T, Target> {
95 _phantom: PhantomData<(T, Target)>,
96}
97
98impl<T, Target> VcRead<T> for VcTransparentRead<T, Target>
99where
100 T: VcValueType,
101 Target: Any + Send + Sync,
102{
103 type Target = Target;
104
105 fn value_to_target_ref(value: &T) -> &Self::Target {
106 unsafe {
112 std::mem::transmute_copy::<ManuallyDrop<&T>, &Self::Target>(&ManuallyDrop::new(value))
113 }
114 }
115
116 fn value_to_target(value: T) -> Self::Target {
117 unsafe {
119 std::mem::transmute_copy::<ManuallyDrop<T>, Self::Target>(&ManuallyDrop::new(value))
120 }
121 }
122
123 fn target_to_value(target: Self::Target) -> T {
124 unsafe {
126 std::mem::transmute_copy::<ManuallyDrop<Self::Target>, T>(&ManuallyDrop::new(target))
127 }
128 }
129
130 fn target_to_value_ref(target: &Self::Target) -> &T {
131 unsafe {
133 std::mem::transmute_copy::<ManuallyDrop<&Self::Target>, &T>(&ManuallyDrop::new(target))
134 }
135 }
136
137 fn target_to_value_mut_ref(target: &mut Self::Target) -> &mut T {
138 unsafe {
140 std::mem::transmute_copy::<ManuallyDrop<&mut Self::Target>, &mut T>(&ManuallyDrop::new(
141 target,
142 ))
143 }
144 }
145}
146
147#[must_use]
148pub struct ReadVcFuture<T, Cast = VcValueTypeCast<T>>
149where
150 T: ?Sized,
151 Cast: VcCast,
152{
153 raw: ReadRawVcFuture,
154 _phantom_t: PhantomData<T>,
155 _phantom_cast: PhantomData<Cast>,
156}
157
158impl<T, Cast> ReadVcFuture<T, Cast>
159where
160 T: ?Sized,
161 Cast: VcCast,
162{
163 pub fn strongly_consistent(mut self) -> Self {
165 self.raw = self.raw.strongly_consistent();
166 self
167 }
168
169 pub fn untracked(mut self) -> Self {
172 self.raw = self.raw.untracked();
173 self
174 }
175
176 pub fn final_read_hint(mut self) -> Self {
179 self.raw = self.raw.final_read_hint();
180 self
181 }
182}
183
184impl<T> ReadVcFuture<T, VcValueTypeCast<T>>
185where
186 T: VcValueType,
187 VcReadTarget<T>: Clone,
188{
189 pub fn owned(self) -> ReadOwnedVcFuture<T> {
191 ReadOwnedVcFuture { future: self }
192 }
193}
194
195impl<T> ReadVcFuture<T, VcValueTypeCast<T>>
196where
197 T: VcValueType,
198 VcReadTarget<T>: KeyedEq,
199{
200 pub fn get<'l, Q>(mut self, key: &'l Q) -> ReadKeyedVcFuture<'l, T, Q>
203 where
204 Q: Hash + ?Sized,
205 VcReadTarget<T>: KeyedAccess<Q>,
206 {
207 self.raw = self.raw.track_with_key(FxBuildHasher.hash_one(key));
208 ReadKeyedVcFuture { future: self, key }
209 }
210
211 pub fn contains_key<'l, Q>(mut self, key: &'l Q) -> ReadContainsKeyedVcFuture<'l, T, Q>
217 where
218 Q: Hash + ?Sized,
219 VcReadTarget<T>: KeyedAccess<Q>,
220 {
221 self.raw = self.raw.track_with_key(FxBuildHasher.hash_one(key));
222 ReadContainsKeyedVcFuture { future: self, key }
223 }
224}
225
226impl<T> From<ReadRawVcFuture> for ReadVcFuture<T, VcValueTypeCast<T>>
227where
228 T: VcValueType,
229{
230 fn from(raw: ReadRawVcFuture) -> Self {
231 Self {
232 raw,
233 _phantom_t: PhantomData,
234 _phantom_cast: PhantomData,
235 }
236 }
237}
238
239impl<T> From<ReadRawVcFuture> for ReadVcFuture<T, VcValueTraitCast<T>>
240where
241 T: VcValueTrait + ?Sized,
242{
243 fn from(raw: ReadRawVcFuture) -> Self {
244 Self {
245 raw,
246 _phantom_t: PhantomData,
247 _phantom_cast: PhantomData,
248 }
249 }
250}
251
252impl<T, Cast> Future for ReadVcFuture<T, Cast>
253where
254 T: ?Sized,
255 Cast: VcCast,
256{
257 type Output = Result<Cast::Output>;
258
259 fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
260 let raw = unsafe { self.map_unchecked_mut(|this| &mut this.raw) };
262 Poll::Ready(std::task::ready!(raw.poll(cx)).and_then(Cast::cast))
263 }
264}
265
266pub struct ReadOwnedVcFuture<T>
267where
268 T: VcValueType,
269 VcReadTarget<T>: Clone,
270{
271 future: ReadVcFuture<T, VcValueTypeCast<T>>,
272}
273
274impl<T> Future for ReadOwnedVcFuture<T>
275where
276 T: VcValueType,
277 VcReadTarget<T>: Clone,
278{
279 type Output = Result<VcReadTarget<T>>;
280
281 fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
282 let future = unsafe { self.map_unchecked_mut(|this| &mut this.future) };
284 match future.poll(cx) {
285 Poll::Ready(Ok(result)) => Poll::Ready(Ok(ReadRef::into_owned(result))),
286 Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
287 Poll::Pending => Poll::Pending,
288 }
289 }
290}
291
292pin_project! {
293 pub struct ReadKeyedVcFuture<'l, T, Q>
294 where
295 T: VcValueType,
296 Q: ?Sized,
297 VcReadTarget<T>: KeyedAccess<Q>,
298
299 {
300 #[pin]
301 future: ReadVcFuture<T, VcValueTypeCast<T>>,
302 key: &'l Q,
303 }
304}
305
306impl<'l, T, Q> Future for ReadKeyedVcFuture<'l, T, Q>
307where
308 T: VcValueType,
309 Q: ?Sized,
310 VcReadTarget<T>: KeyedAccess<Q>,
311{
312 type Output = Result<Option<MappedReadRef<T, <VcReadTarget<T> as KeyedAccess<Q>>::Value>>>;
313
314 fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
315 let this = self.project();
317 match this.future.poll(cx) {
318 Poll::Ready(Ok(result)) => {
319 let mapped_read_ref = if let Some(value) = (*result).get(this.key) {
320 let ptr = value as *const _;
321 Some(unsafe { MappedReadRef::new(result.into_raw_arc(), ptr) })
322 } else {
323 None
324 };
325 Poll::Ready(Ok(mapped_read_ref))
326 }
327 Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
328 Poll::Pending => Poll::Pending,
329 }
330 }
331}
332
333pin_project! {
334 pub struct ReadContainsKeyedVcFuture<'l, T, Q>
335 where
336 T: VcValueType,
337 Q: ?Sized,
338 VcReadTarget<T>: KeyedAccess<Q>,
339 {
340 #[pin]
341 future: ReadVcFuture<T, VcValueTypeCast<T>>,
342 key: &'l Q,
343 }
344}
345
346impl<'l, T, Q> Future for ReadContainsKeyedVcFuture<'l, T, Q>
347where
348 T: VcValueType,
349 Q: ?Sized,
350 VcReadTarget<T>: KeyedAccess<Q>,
351{
352 type Output = Result<bool>;
353
354 fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
355 let this = self.project();
357 match this.future.poll(cx) {
358 Poll::Ready(Ok(result)) => {
359 let result = (*result).contains_key(this.key);
360 Poll::Ready(Ok(result))
361 }
362 Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
363 Poll::Pending => Poll::Pending,
364 }
365 }
366}