Skip to main content

turbo_tasks/
read_ref.rs

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::{ResolvedVc, SharedReference, Vc, VcRead, VcValueType, vc::VcCellMode};
22
23type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
24
25/// The read value of a value cell. The read value is immutable, while the cell
26/// itself might change over time. It's basically a snapshot of a value at a
27/// certain point in time.
28///
29/// Internally it stores a reference counted reference to a value on the heap.
30pub struct ReadRef<T>(pub(crate) triomphe::Arc<T>);
31
32impl<T> Clone for ReadRef<T> {
33    fn clone(&self) -> Self {
34        Self(self.0.clone())
35    }
36}
37
38impl<T> Deref for ReadRef<T>
39where
40    T: VcValueType,
41{
42    type Target = VcReadTarget<T>;
43
44    fn deref(&self) -> &Self::Target {
45        T::Read::value_to_target_ref(&self.0)
46    }
47}
48
49impl<T> Display for ReadRef<T>
50where
51    T: VcValueType,
52    VcReadTarget<T>: Display,
53{
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        Display::fmt(&**self, f)
56    }
57}
58
59impl<T> Debug for ReadRef<T>
60where
61    T: Debug,
62{
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        Self::as_raw_ref(self).fmt(f)
65    }
66}
67
68#[cfg(debug_assertions)]
69impl<T> ValueDebugFormat for ReadRef<T>
70where
71    T: VcValueType,
72    VcReadTarget<T>: ValueDebugFormat + 'static,
73{
74    fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString<'_> {
75        let value = &**self;
76        value.value_debug_format(depth)
77    }
78}
79
80impl<T> PartialEq for ReadRef<T>
81where
82    T: Eq,
83{
84    fn eq(&self, other: &Self) -> bool {
85        // Fast path: if both point to the same allocation, they're equal.
86        Self::ptr_eq(self, other) || Self::as_raw_ref(self).eq(Self::as_raw_ref(other))
87    }
88}
89
90impl<T> Eq for ReadRef<T> where T: Eq {}
91
92impl<T> PartialOrd for ReadRef<T>
93where
94    T: PartialOrd + Eq,
95{
96    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
97        Self::as_raw_ref(self).partial_cmp(Self::as_raw_ref(other))
98    }
99}
100
101impl<T> Ord for ReadRef<T>
102where
103    T: Ord + Eq,
104{
105    fn cmp(&self, other: &Self) -> Ordering {
106        Self::as_raw_ref(self).cmp(Self::as_raw_ref(other))
107    }
108}
109
110impl<T> Hash for ReadRef<T>
111where
112    T: Hash,
113{
114    fn hash<H: Hasher>(&self, state: &mut H) {
115        Self::as_raw_ref(self).hash(state)
116    }
117}
118
119impl<T> DeterministicHash for ReadRef<T>
120where
121    T: VcValueType,
122    VcReadTarget<T>: DeterministicHash,
123{
124    fn deterministic_hash<H: turbo_tasks_hash::DeterministicHasher>(&self, state: &mut H) {
125        let p = &**self;
126        p.deterministic_hash(state);
127    }
128}
129
130/// Iterate by reference over a [`ReadRef`].
131impl<'a, T, I, J: Iterator<Item = I>> IntoIterator for &'a ReadRef<T>
132where
133    T: VcValueType,
134    &'a VcReadTarget<T>: IntoIterator<Item = I, IntoIter = J>,
135{
136    type Item = I;
137
138    type IntoIter = J;
139
140    fn into_iter(self) -> Self::IntoIter {
141        (&**self).into_iter()
142    }
143}
144
145impl<T, I, J> IntoIterator for ReadRef<T>
146where
147    T: VcValueType,
148    I: Copy + 'static,
149    J: Iterator<Item = &'static I> + 'static,
150    &'static VcReadTarget<T>: IntoIterator<Item = &'static I, IntoIter = J>,
151{
152    type Item = I;
153    type IntoIter = ReadRefIter<T, I, J>;
154
155    fn into_iter(self) -> Self::IntoIter {
156        let r: &VcReadTarget<T> = &self;
157        // SAFETY: The `&'static` reference fabricated here is only stored in
158        // `iter`, which lives inside the returned `ReadRefIter` alongside the
159        // `ReadRef` that owns the data. The public `Iterator::next` only
160        // returns `Copy`-ed-out values — no reference (with the fake `'static`
161        // lifetime or otherwise) ever leaves the iterator. Struct-field drop
162        // order (`iter` then `_read_ref`) drops any references still held by
163        // `iter` before the backing storage.
164        let r = unsafe { std::mem::transmute::<&VcReadTarget<T>, &'static VcReadTarget<T>>(r) };
165        ReadRefIter {
166            iter: r.into_iter(),
167            _read_ref: self,
168        }
169    }
170}
171
172/// Consuming iteration over a [`ReadRef`], yielding items by **copy**.
173///
174/// `Iterator::Item` is a fixed associated type — it cannot borrow from
175/// `&mut self`.
176///
177/// The iterator owns the original [`ReadRef`], borrows into the underlying value, and
178/// `Iterator::next` simply copies each element out of that borrow. This restricts the impl to
179/// element types that are [`Copy`] — typically `ResolvedVc<_>`, integer ids, etc. For
180/// non-`Copy` element types (or if you want zero-copy iteration over
181/// borrows), iterate by reference instead: `for item in &read_ref { ... }`.
182pub struct ReadRefIter<T, I, J>
183where
184    T: VcValueType,
185    I: Copy + 'static,
186    J: Iterator<Item = &'static I>,
187{
188    iter: J,
189    _read_ref: ReadRef<T>,
190}
191
192impl<T, I, J> Iterator for ReadRefIter<T, I, J>
193where
194    T: VcValueType,
195    I: Copy + 'static,
196    J: Iterator<Item = &'static I>,
197{
198    type Item = I;
199
200    fn next(&mut self) -> Option<I> {
201        self.iter.next().copied()
202    }
203}
204
205impl<T> Serialize for ReadRef<T>
206where
207    T: Serialize,
208{
209    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
210    where
211        S: serde::Serializer,
212    {
213        Self::as_raw_ref(self).serialize(serializer)
214    }
215}
216
217impl<'de, T> Deserialize<'de> for ReadRef<T>
218where
219    T: Deserialize<'de>,
220{
221    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
222    where
223        D: serde::Deserializer<'de>,
224    {
225        let value = T::deserialize(deserializer)?;
226        Ok(Self(triomphe::Arc::new(value)))
227    }
228}
229
230impl<T> Encode for ReadRef<T>
231where
232    T: Encode,
233{
234    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
235        Self::as_raw_ref(self).encode(encoder)
236    }
237}
238
239impl<Context, T> Decode<Context> for ReadRef<T>
240where
241    T: Decode<Context>,
242{
243    fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
244        let value = T::decode(decoder)?;
245        Ok(Self(triomphe::Arc::new(value)))
246    }
247}
248
249impl_borrow_decode_with_context!(ReadRef<T>, Context, Context, T: Decode<Context>);
250
251impl<T> ReadRef<T> {
252    pub fn new_owned(value: T) -> Self {
253        Self(triomphe::Arc::new(value))
254    }
255
256    pub fn new_arc(arc: triomphe::Arc<T>) -> Self {
257        Self(arc)
258    }
259
260    /// Returns the reference to `&T`, rather than `<<T as VcValueType>::Read as VcRead<T>>::Target`
261    /// (the behavior of [`Deref`]).
262    pub fn as_raw_ref(this: &ReadRef<T>) -> &T {
263        &this.0
264    }
265
266    /// Returns the inner `Arc<T>`.
267    pub fn into_raw_arc(self) -> triomphe::Arc<T> {
268        self.0
269    }
270
271    pub fn ptr_eq(&self, other: &ReadRef<T>) -> bool {
272        triomphe::Arc::ptr_eq(&self.0, &other.0)
273    }
274
275    pub fn ptr(&self) -> *const T {
276        &*self.0 as *const T
277    }
278}
279
280impl<T> ReadRef<T>
281where
282    T: VcValueType,
283{
284    /// Returns a new [`Vc`] that points to the same value as the given reference.
285    pub fn cell(read_ref: ReadRef<T>) -> Vc<T> {
286        let type_id = T::get_value_type_id();
287        Vc {
288            node: <T::CellMode as VcCellMode<T>>::raw_cell(
289                SharedReference::new(read_ref.0).into_typed(type_id),
290            ),
291            _t: PhantomData,
292        }
293    }
294
295    /// Returns a new [`ResolvedVc`] that points to the same value as the given reference.
296    pub fn resolved_cell(read_ref: ReadRef<T>) -> ResolvedVc<T> {
297        ResolvedVc {
298            node: ReadRef::cell(read_ref),
299        }
300    }
301}
302
303impl<T> ReadRef<T>
304where
305    T: VcValueType,
306{
307    /// Returns the inner value, if this [`ReadRef`] has exactly one strong reference.
308    ///
309    /// Otherwise, an [`Err`] is returned with the same [`ReadRef`] that was passed in.
310    pub fn try_unwrap(this: Self) -> Result<VcReadTarget<T>, Self> {
311        match triomphe::Arc::try_unwrap(this.0) {
312            Ok(value) => Ok(T::Read::value_to_target(value)),
313            Err(arc) => Err(Self(arc)),
314        }
315    }
316}
317
318impl<T> ReadRef<T>
319where
320    T: VcValueType,
321    VcReadTarget<T>: Clone,
322{
323    /// This is return a owned version of the value. It potentially clones the value.
324    /// The clone might be expensive. Prefer Deref to get a reference to the value.
325    pub fn into_owned(this: Self) -> VcReadTarget<T> {
326        Self::try_unwrap(this).unwrap_or_else(|this| (*this).clone())
327    }
328}