turbo_tasks/
read_ref.rs

1use std::{
2    cmp::Ordering,
3    fmt::{self, Debug, Display},
4    hash::{Hash, Hasher},
5    marker::PhantomData,
6    mem::transmute_copy,
7    ops::Deref,
8};
9
10use bincode::{
11    Decode, Encode,
12    de::Decoder,
13    enc::Encoder,
14    error::{DecodeError, EncodeError},
15    impl_borrow_decode_with_context,
16};
17use serde::{Deserialize, Serialize};
18use turbo_tasks_hash::DeterministicHash;
19
20use crate::{
21    SharedReference, Vc, VcRead, VcValueType,
22    debug::{ValueDebugFormat, ValueDebugFormatString},
23    trace::{TraceRawVcs, TraceRawVcsContext},
24    triomphe_utils::unchecked_sidecast_triomphe_arc,
25    vc::VcCellMode,
26};
27
28type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
29
30/// The read value of a value cell. The read value is immutable, while the cell
31/// itself might change over time. It's basically a snapshot of a value at a
32/// certain point in time.
33///
34/// Internally it stores a reference counted reference to a value on the heap.
35pub struct ReadRef<T>(triomphe::Arc<T>);
36
37impl<T> Clone for ReadRef<T> {
38    fn clone(&self) -> Self {
39        Self(self.0.clone())
40    }
41}
42
43impl<T> Deref for ReadRef<T>
44where
45    T: VcValueType,
46{
47    type Target = VcReadTarget<T>;
48
49    fn deref(&self) -> &Self::Target {
50        T::Read::value_to_target_ref(&self.0)
51    }
52}
53
54impl<T> Display for ReadRef<T>
55where
56    T: VcValueType,
57    VcReadTarget<T>: Display,
58{
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        Display::fmt(&**self, f)
61    }
62}
63
64impl<T> Debug for ReadRef<T>
65where
66    T: Debug,
67{
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        Self::as_raw_ref(self).fmt(f)
70    }
71}
72
73impl<T> TraceRawVcs for ReadRef<T>
74where
75    T: TraceRawVcs,
76{
77    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
78        Self::as_raw_ref(self).trace_raw_vcs(trace_context);
79    }
80}
81
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: PartialEq,
96{
97    fn eq(&self, other: &Self) -> bool {
98        Self::as_raw_ref(self).eq(Self::as_raw_ref(other))
99    }
100}
101
102impl<T> Eq for ReadRef<T> where T: Eq {}
103
104impl<T> PartialOrd for ReadRef<T>
105where
106    T: PartialOrd,
107{
108    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
109        Self::as_raw_ref(self).partial_cmp(Self::as_raw_ref(other))
110    }
111}
112
113impl<T> Ord for ReadRef<T>
114where
115    T: Ord,
116{
117    fn cmp(&self, other: &Self) -> Ordering {
118        Self::as_raw_ref(self).cmp(Self::as_raw_ref(other))
119    }
120}
121
122impl<T> Hash for ReadRef<T>
123where
124    T: Hash,
125{
126    fn hash<H: Hasher>(&self, state: &mut H) {
127        Self::as_raw_ref(self).hash(state)
128    }
129}
130
131impl<T> DeterministicHash for ReadRef<T>
132where
133    T: VcValueType,
134    VcReadTarget<T>: DeterministicHash,
135{
136    fn deterministic_hash<H: turbo_tasks_hash::DeterministicHasher>(&self, state: &mut H) {
137        let p = &**self;
138        p.deterministic_hash(state);
139    }
140}
141
142impl<'a, T, I, J: Iterator<Item = I>> IntoIterator for &'a ReadRef<T>
143where
144    T: VcValueType,
145    &'a VcReadTarget<T>: IntoIterator<Item = I, IntoIter = J>,
146{
147    type Item = I;
148
149    type IntoIter = J;
150
151    fn into_iter(self) -> Self::IntoIter {
152        (&**self).into_iter()
153    }
154}
155
156impl<T, I: 'static, J: Iterator<Item = I>> IntoIterator for ReadRef<T>
157where
158    T: VcValueType,
159    &'static VcReadTarget<T>: IntoIterator<Item = I, IntoIter = J>,
160{
161    type Item = I;
162
163    type IntoIter = ReadRefIter<T, I, J>;
164
165    fn into_iter(self) -> Self::IntoIter {
166        let r = &*self;
167        // # Safety
168        // The reference will we valid as long as the ReadRef is valid.
169        let r = unsafe { transmute_copy::<&'_ VcReadTarget<T>, &'static VcReadTarget<T>>(&r) };
170        ReadRefIter {
171            read_ref: self,
172            iter: r.into_iter(),
173        }
174    }
175}
176
177pub struct ReadRefIter<T, I: 'static, J: Iterator<Item = I>>
178where
179    T: VcValueType,
180{
181    iter: J,
182    #[allow(dead_code)]
183    read_ref: ReadRef<T>,
184}
185
186impl<T, I: 'static, J: Iterator<Item = I>> Iterator for ReadRefIter<T, I, J>
187where
188    T: VcValueType,
189{
190    type Item = I;
191
192    fn next(&mut self) -> Option<Self::Item> {
193        self.iter.next()
194    }
195}
196
197impl<T> Serialize for ReadRef<T>
198where
199    T: Serialize,
200{
201    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
202    where
203        S: serde::Serializer,
204    {
205        Self::as_raw_ref(self).serialize(serializer)
206    }
207}
208
209impl<'de, T> Deserialize<'de> for ReadRef<T>
210where
211    T: Deserialize<'de>,
212{
213    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
214    where
215        D: serde::Deserializer<'de>,
216    {
217        let value = T::deserialize(deserializer)?;
218        Ok(Self(triomphe::Arc::new(value)))
219    }
220}
221
222impl<T> Encode for ReadRef<T>
223where
224    T: Encode,
225{
226    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
227        Self::as_raw_ref(self).encode(encoder)
228    }
229}
230
231impl<Context, T> Decode<Context> for ReadRef<T>
232where
233    T: Decode<Context>,
234{
235    fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
236        let value = T::decode(decoder)?;
237        Ok(Self(triomphe::Arc::new(value)))
238    }
239}
240
241impl_borrow_decode_with_context!(ReadRef<T>, Context, Context, T: Decode<Context>);
242
243impl<T> ReadRef<T> {
244    pub fn new_owned(value: T) -> Self {
245        Self(triomphe::Arc::new(value))
246    }
247
248    pub fn new_arc(arc: triomphe::Arc<T>) -> Self {
249        Self(arc)
250    }
251
252    /// Returns the reference to `&T`, rather than `<<T as VcValueType>::Read as VcRead<T>>::Target`
253    /// (the behavior of [`Deref`]).
254    pub fn as_raw_ref(this: &ReadRef<T>) -> &T {
255        &this.0
256    }
257
258    pub fn ptr_eq(&self, other: &ReadRef<T>) -> bool {
259        triomphe::Arc::ptr_eq(&self.0, &other.0)
260    }
261
262    pub fn ptr(&self) -> *const T {
263        &*self.0 as *const T
264    }
265}
266
267impl<T> ReadRef<T>
268where
269    T: VcValueType,
270{
271    /// Returns a new cell that points to the same value as the given
272    /// reference.
273    pub fn cell(read_ref: ReadRef<T>) -> Vc<T> {
274        let type_id = T::get_value_type_id();
275        // SAFETY: `T` and `T::Read::Repr` must have equivalent memory representations,
276        // guaranteed by the unsafe implementation of `VcValueType`.
277        let value = unsafe {
278            unchecked_sidecast_triomphe_arc::<T, <T::Read as VcRead<T>>::Repr>(read_ref.0)
279        };
280        Vc {
281            node: <T::CellMode as VcCellMode<T>>::raw_cell(
282                SharedReference::new(value).into_typed(type_id),
283            ),
284            _t: PhantomData,
285        }
286    }
287}
288
289impl<T> ReadRef<T>
290where
291    T: VcValueType,
292{
293    /// Returns the inner value, if this [`ReadRef`] has exactly one strong reference.
294    ///
295    /// Otherwise, an [`Err`] is returned with the same [`ReadRef`] that was passed in.
296    pub fn try_unwrap(this: Self) -> Result<VcReadTarget<T>, Self> {
297        match triomphe::Arc::try_unwrap(this.0) {
298            Ok(value) => Ok(T::Read::value_to_target(value)),
299            Err(arc) => Err(Self(arc)),
300        }
301    }
302}
303
304impl<T> ReadRef<T>
305where
306    T: VcValueType,
307    VcReadTarget<T>: Clone,
308{
309    /// This is return a owned version of the value. It potentially clones the value.
310    /// The clone might be expensive. Prefer Deref to get a reference to the value.
311    pub fn into_owned(this: Self) -> VcReadTarget<T> {
312        Self::try_unwrap(this).unwrap_or_else(|this| (*this).clone())
313    }
314}