1use std::{
2 cmp::Ordering,
3 fmt::{self, Debug, Display},
4 hash::{Hash, Hasher},
5 marker::PhantomData,
6 ops::Deref,
7};
8
9use bincode::{
10 Decode, Encode,
11 de::Decoder,
12 enc::Encoder,
13 error::{DecodeError, EncodeError},
14 impl_borrow_decode_with_context,
15};
16use serde::{Deserialize, Serialize};
17use turbo_tasks_hash::DeterministicHash;
18
19#[cfg(debug_assertions)]
20use crate::debug::{ValueDebugFormat, ValueDebugFormatString};
21use crate::{
22 ResolvedVc, SharedReference, Vc, VcRead, VcValueType,
23 trace::{TraceRawVcs, TraceRawVcsContext},
24 vc::VcCellMode,
25};
26
27type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
28
29pub struct ReadRef<T>(pub(crate) triomphe::Arc<T>);
35
36impl<T> Clone for ReadRef<T> {
37 fn clone(&self) -> Self {
38 Self(self.0.clone())
39 }
40}
41
42impl<T> Deref for ReadRef<T>
43where
44 T: VcValueType,
45{
46 type Target = VcReadTarget<T>;
47
48 fn deref(&self) -> &Self::Target {
49 T::Read::value_to_target_ref(&self.0)
50 }
51}
52
53impl<T> Display for ReadRef<T>
54where
55 T: VcValueType,
56 VcReadTarget<T>: Display,
57{
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 Display::fmt(&**self, f)
60 }
61}
62
63impl<T> Debug for ReadRef<T>
64where
65 T: Debug,
66{
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 Self::as_raw_ref(self).fmt(f)
69 }
70}
71
72impl<T> TraceRawVcs for ReadRef<T>
73where
74 T: TraceRawVcs,
75{
76 fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
77 Self::as_raw_ref(self).trace_raw_vcs(trace_context);
78 }
79}
80
81#[cfg(debug_assertions)]
82impl<T> ValueDebugFormat for ReadRef<T>
83where
84 T: VcValueType,
85 VcReadTarget<T>: ValueDebugFormat + 'static,
86{
87 fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString<'_> {
88 let value = &**self;
89 value.value_debug_format(depth)
90 }
91}
92
93impl<T> PartialEq for ReadRef<T>
94where
95 T: Eq,
96{
97 fn eq(&self, other: &Self) -> bool {
98 Self::ptr_eq(self, other) || Self::as_raw_ref(self).eq(Self::as_raw_ref(other))
100 }
101}
102
103impl<T> Eq for ReadRef<T> where T: Eq {}
104
105impl<T> PartialOrd for ReadRef<T>
106where
107 T: PartialOrd + Eq,
108{
109 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
110 Self::as_raw_ref(self).partial_cmp(Self::as_raw_ref(other))
111 }
112}
113
114impl<T> Ord for ReadRef<T>
115where
116 T: Ord + Eq,
117{
118 fn cmp(&self, other: &Self) -> Ordering {
119 Self::as_raw_ref(self).cmp(Self::as_raw_ref(other))
120 }
121}
122
123impl<T> Hash for ReadRef<T>
124where
125 T: Hash,
126{
127 fn hash<H: Hasher>(&self, state: &mut H) {
128 Self::as_raw_ref(self).hash(state)
129 }
130}
131
132impl<T> DeterministicHash for ReadRef<T>
133where
134 T: VcValueType,
135 VcReadTarget<T>: DeterministicHash,
136{
137 fn deterministic_hash<H: turbo_tasks_hash::DeterministicHasher>(&self, state: &mut H) {
138 let p = &**self;
139 p.deterministic_hash(state);
140 }
141}
142
143impl<'a, T, I, J: Iterator<Item = I>> IntoIterator for &'a ReadRef<T>
145where
146 T: VcValueType,
147 &'a VcReadTarget<T>: IntoIterator<Item = I, IntoIter = J>,
148{
149 type Item = I;
150
151 type IntoIter = J;
152
153 fn into_iter(self) -> Self::IntoIter {
154 (&**self).into_iter()
155 }
156}
157
158impl<T, I, J> IntoIterator for ReadRef<T>
159where
160 T: VcValueType,
161 I: Copy + 'static,
162 J: Iterator<Item = &'static I> + 'static,
163 &'static VcReadTarget<T>: IntoIterator<Item = &'static I, IntoIter = J>,
164{
165 type Item = I;
166 type IntoIter = ReadRefIter<T, I, J>;
167
168 fn into_iter(self) -> Self::IntoIter {
169 let r: &VcReadTarget<T> = &self;
170 let r = unsafe { std::mem::transmute::<&VcReadTarget<T>, &'static VcReadTarget<T>>(r) };
178 ReadRefIter {
179 iter: r.into_iter(),
180 _read_ref: self,
181 }
182 }
183}
184
185pub struct ReadRefIter<T, I, J>
196where
197 T: VcValueType,
198 I: Copy + 'static,
199 J: Iterator<Item = &'static I>,
200{
201 iter: J,
202 _read_ref: ReadRef<T>,
203}
204
205impl<T, I, J> Iterator for ReadRefIter<T, I, J>
206where
207 T: VcValueType,
208 I: Copy + 'static,
209 J: Iterator<Item = &'static I>,
210{
211 type Item = I;
212
213 fn next(&mut self) -> Option<I> {
214 self.iter.next().copied()
215 }
216}
217
218impl<T> Serialize for ReadRef<T>
219where
220 T: Serialize,
221{
222 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
223 where
224 S: serde::Serializer,
225 {
226 Self::as_raw_ref(self).serialize(serializer)
227 }
228}
229
230impl<'de, T> Deserialize<'de> for ReadRef<T>
231where
232 T: Deserialize<'de>,
233{
234 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
235 where
236 D: serde::Deserializer<'de>,
237 {
238 let value = T::deserialize(deserializer)?;
239 Ok(Self(triomphe::Arc::new(value)))
240 }
241}
242
243impl<T> Encode for ReadRef<T>
244where
245 T: Encode,
246{
247 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
248 Self::as_raw_ref(self).encode(encoder)
249 }
250}
251
252impl<Context, T> Decode<Context> for ReadRef<T>
253where
254 T: Decode<Context>,
255{
256 fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
257 let value = T::decode(decoder)?;
258 Ok(Self(triomphe::Arc::new(value)))
259 }
260}
261
262impl_borrow_decode_with_context!(ReadRef<T>, Context, Context, T: Decode<Context>);
263
264impl<T> ReadRef<T> {
265 pub fn new_owned(value: T) -> Self {
266 Self(triomphe::Arc::new(value))
267 }
268
269 pub fn new_arc(arc: triomphe::Arc<T>) -> Self {
270 Self(arc)
271 }
272
273 pub fn as_raw_ref(this: &ReadRef<T>) -> &T {
276 &this.0
277 }
278
279 pub fn into_raw_arc(self) -> triomphe::Arc<T> {
281 self.0
282 }
283
284 pub fn ptr_eq(&self, other: &ReadRef<T>) -> bool {
285 triomphe::Arc::ptr_eq(&self.0, &other.0)
286 }
287
288 pub fn ptr(&self) -> *const T {
289 &*self.0 as *const T
290 }
291}
292
293impl<T> ReadRef<T>
294where
295 T: VcValueType,
296{
297 pub fn cell(read_ref: ReadRef<T>) -> Vc<T> {
299 let type_id = T::get_value_type_id();
300 Vc {
301 node: <T::CellMode as VcCellMode<T>>::raw_cell(
302 SharedReference::new(read_ref.0).into_typed(type_id),
303 ),
304 _t: PhantomData,
305 }
306 }
307
308 pub fn resolved_cell(read_ref: ReadRef<T>) -> ResolvedVc<T> {
310 ResolvedVc {
311 node: ReadRef::cell(read_ref),
312 }
313 }
314}
315
316impl<T> ReadRef<T>
317where
318 T: VcValueType,
319{
320 pub fn try_unwrap(this: Self) -> Result<VcReadTarget<T>, Self> {
324 match triomphe::Arc::try_unwrap(this.0) {
325 Ok(value) => Ok(T::Read::value_to_target(value)),
326 Err(arc) => Err(Self(arc)),
327 }
328 }
329}
330
331impl<T> ReadRef<T>
332where
333 T: VcValueType,
334 VcReadTarget<T>: Clone,
335{
336 pub fn into_owned(this: Self) -> VcReadTarget<T> {
339 Self::try_unwrap(this).unwrap_or_else(|this| (*this).clone())
340 }
341}