turbo_tasks/
read_ref.rs

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